#!/usr/bin/env python
# -*- coding: utf_8 -*-

import copy
import time
import types
import json
import logging
import traceback
from datetime import datetime
from pony.orm import *
from flask import request
from app import signalManager
from model import fullStackDB
from model.annex import Annex
from model.apps import Apps
from model.user import User
from utils import sql_filter, ThreadMaker

logger = logging.getLogger("AppsManager")

@ThreadMaker
def build_application(uuid):
    signalManager.actionAddBuildLog.emit(uuid)

class AppsManager(object):
    def __init__(self):
        super(AppsManager, self).__init__()

    def add(self, data):
        with db_session:
            result = Apps.get(app_name=data.get("app_name"), is_delete=False)
            if result:
                return False, "app_name has been exists."

            editor = User.get(id=request.current_user.get("id"))
            if not editor:
                return False, "current user is not exists"

            data.update({
                'create_by': editor,
                'create_at': datetime.now(),
                'update_by': editor,
                'update_at': datetime.now(),
            })

            icon = Annex(title=data.get("app_icon").get("filename"), path=data.get("app_icon").get("filepath"), size=data.get("app_icon").get("filesize"), create_by=editor, create_at=datetime.now(), update_by=editor, update_at=datetime.now())
            commit()

            app_files = []
            if data.get("app_files"):
                app_files = data.get("app_files")
                data.pop("app_files")
                data.update({ "app_icon": icon })

            result = Apps(**data)
            commit()

            if result:
                for a in app_files:
                    Annex(app=result, title=a.get("filename"), path=a.get("filepath"), size=a.get("filesize"), create_by=editor, create_at=datetime.now(), update_by=editor, update_at=datetime.now())
                    flush()
                commit()

            build_application(str(result.uuid))

            return result, "add app {}.".format("success" if result else "fail")

    def delete(self, uuid):
        editor = User.get(id=request.current_user.get("id"))
        if not editor:
            return False, "current user is not exists"

        result = fullStackDB.update(Apps, { 'uuid': uuid }, is_delete=True, delete_at=datetime.now(), delete_by=editor)
        return result, "delete app {}.".format("success" if result else "fail")

    def get(self, data):
        result = Apps.get(**data)
        if result:
            result = result.to_dict(only=["uuid", "name", "create_at", "update_at"])
        return result, "get app {}.".format("success" if result else "no data")

    def getList(self, data):
        if not data or len(data) <= 0:
            return False, 0, "parameters can not be null."

        temp = copy.deepcopy(data)
        if 'pagenum' in temp:
            temp.pop('pagenum')
        if 'pagesize' in temp:
            temp.pop('pagesize')
        if 'scope_type' in temp:
            temp.pop('scope_type')
        temp.setdefault("is_delete", False)

        with db_session:
            if "scope_type" in data and data.get("scope_type") == "list":
                result = Apps.select().where(**temp).order_by(desc(Apps.create_at))
                temp = []
                for item in result:
                    temp.append(item.to_dict(only=["uuid", "app_name"]))
                return temp, len(temp), "get app {}.".format("success" if temp else "fail")

            result = Apps.select().where(**temp).order_by(Apps.sort).page(data.get("pagenum", 1), pagesize=data.get("pagesize", 10))
            count = Apps.select().where(**temp).count()

            if result and len(result):
                temp = []
                for item in result:
                    t = item.to_dict(with_collections=True, related_objects=True, exclude=["app_annex", "app_build_log", "app_download", "is_delete", "delete_by", "delete_at"])
                    t.update({
                        "app_icon": item.app_icon.to_dict(only=["path"]),
                        "create_by": item.create_by.to_dict(only=["uuid", "username"]),
                        "update_by": item.update_by.to_dict(only=["uuid", "username"]),
                        "create_at": item.create_at.strftime("%Y-%m-%d %H:%M:%S") if item.create_at else None,
                        "update_at": item.update_at.strftime("%Y-%m-%d %H:%M:%S") if item.update_at else None,
                    })
                    temp.append(t)
                result = temp

            return result, count, "get app {}.".format("success" if result else "no data")

    def update(self, uuid, data):
        # 当参数为空时,直接返回错误
        if len(data) <= 0 or (len(data.keys()) == 1 and "id" in data):
            return False, "app can not be null."

        with db_session:
            editor = User.get(id=request.current_user.get("id"))
            if not editor:
                return False, "current user is not exists"

            result = Apps.get(uuid=uuid)
            if not result:
                return False, "app not found"

            if data.get("app_files"):
                app_files = data.get("app_files")
                for a in app_files:
                    Annex(app=result, title=a.get("filename"), path=a.get("filepath"), size=a.get("filesize"), create_by=editor, create_at=datetime.now(), update_by=editor, update_at=datetime.now())
                    flush()
                commit()
                data.pop("app_files")

            if data.get("app_icon"):
                condition = {
                    'update_by': editor,
                    'update_at': datetime.now()
                }
                if data.get("app_icon").get("filename"):
                    condition.update({"title": data.get("app_icon").get("filename")})
                if data.get("app_icon").get("filepath"):
                    condition.update({"path": data.get("app_icon").get("filepath")})
                if data.get("app_icon").get("filesize"):
                    condition.update({"size": data.get("app_icon").get("filesize")})

                result.app_icon.set(**condition)
                commit()
                data.pop("app_icon")

            result.set(update_at=datetime.now(), update_by=editor, **data)
            commit()

            build_application(str(result.uuid))

            return result, "update app {}.".format("success" if result else "fail")

appsManager = AppsManager()