'''
Author: your name
Date: 2021-07-19 14:29:33
LastEditTime: 2021-07-23 00:37:20
LastEditors: Please set LastEditors
Description: In User Settings Edit
FilePath: \evm-store\tools\build_out\views\api.py
'''
#!/usr/bin/env python
# -*- coding: utf_8 -*-

import os
import time
import json
import random
import traceback
import uuid
from pathlib import Path
from datetime import datetime, timedelta
from flask import current_app, jsonify, request, Response
from flask_restful import Resource
from flask_restful.reqparse import RequestParser
from flask_jwt_extended import (jwt_required, get_jwt_identity)
from werkzeug.utils import secure_filename
from werkzeug.datastructures import FileStorage
from marshmallow.exceptions import ValidationError
from application.app import db
from application.config import config
from application.signal_manager import signalManager
from models import MyModel, MyModel2
from models.app import AppModel
from models.annex import AnnexModel
from models.login import LoginModel
from models.device import DeviceModel
from models.package import PackageModel
from models.monitorEvm import MonitorEvmModel
from models.monitorLvgl import MonitorLvglModel
from models.monitorImage import MonitorImageModel
from models.monitorWatch import MonitorWatchModel
from models.monitorSystem import MonitorSystemModel
from webcreator.log import logger
from webcreator.utils.ccode import convert_string
from webcreator.response import ResponseCode, response_result


class AppReviewResource(Resource):
    def __init__(self):
        self.parser = RequestParser()

    # 设置启动器接口
    @jwt_required(locations=["headers"])
    def get(self):
        self.parser.add_argument(
            "app", type=str, location="args", required=False)
        args = self.parser.parse_args()

        try:
            data = dict()
            for key, value in args.items():
                if value != None:
                    data[key] = value

            jwt = get_jwt_identity()
            result, message = signalManager.actionSetLauncher.emit(data, jwt)
            if result:
                return response_result(message, data=result)
            return response_result(message)
        except ValidationError as e:
            return response_result(ResponseCode.HTTP_INVAILD_REQUEST, data=e.messages)
        except Exception as e:
            data = None
            if hasattr(e, 'args'):
                data = e.args
            traceback.print_exc()
            current_app.logger.error(e)
            return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data)

    @jwt_required(locations=["headers"])
    def post(self):
        self.parser.add_argument(
            "review", type=int, location="json", default=0, required=True)
        self.parser.add_argument(
            "app", type=str, location="json", required=False)
        args = self.parser.parse_args()

        try:
            jwt = get_jwt_identity()
            result, message = signalManager.actionPostAppReview.emit(
                args.app, args.review, jwt)
            if result:
                return response_result(message, data=result)
            return response_result(message)
        except ValidationError as e:
            return response_result(ResponseCode.HTTP_INVAILD_REQUEST, data=e.messages)
        except Exception as e:
            data = None
            if hasattr(e, 'args'):
                data = e.args
            traceback.print_exc()
            current_app.logger.error(e)
            return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data)


class BuildAppResource(Resource):
    def __init__(self):
        self.parser = RequestParser()

    def get(self):
        try:
            return ResponseCode.HTTP_SUCCESS
            
            result = db.session.query(AnnexModel).all()
            for item in result:
                item.uuid = uuid.uuid1().hex
                logger.info(item.uuid)
                db.session.flush()
            db.session.commit()

            result = db.session.query(AppModel).all()
            for item in result:
                item.uuid = uuid.uuid1().hex
                logger.info(item.uuid)
                db.session.flush()
            db.session.commit()

            result = db.session.query(LoginModel).all()
            for item in result:
                item.uuid = uuid.uuid1().hex
                logger.info(item.uuid)
                db.session.flush()
            db.session.commit()

            result = db.session.query(DeviceModel).all()
            for item in result:
                item.uuid = uuid.uuid1().hex
                logger.info(item.uuid)
                db.session.flush()
            db.session.commit()

            result = db.session.query(PackageModel).all()
            for item in result:
                item.uuid = uuid.uuid1().hex
                if item.source == None:
                    item.source = 0
                logger.info(item.uuid)
                db.session.flush()
            db.session.commit()

            result = db.session.query(MonitorEvmModel).all()
            for item in result:
                item.uuid = uuid.uuid1().hex
                logger.info(item.uuid)
                db.session.flush()
            db.session.commit()

            result = db.session.query(MonitorLvglModel).all()
            for item in result:
                item.uuid = uuid.uuid1().hex
                logger.info(item.uuid)
                db.session.flush()
            db.session.commit()

            result = db.session.query(MonitorImageModel).all()
            for item in result:
                item.uuid = uuid.uuid1().hex
                logger.info(item.uuid)
                db.session.flush()
            db.session.commit()

            result = db.session.query(MonitorWatchModel).all()
            for item in result:
                item.uuid = uuid.uuid1().hex
                logger.info(item.uuid)
                db.session.flush()
            db.session.commit()

            # result_proxy = conn.execute("select id, host, path, protocol, create_at from monitor_request")
            # result = result_proxy.fetchall()
            result = db.session.query(MyModel2).filter().all()
            for item in result:
                res = MonitorSystemModel.query.filter(
                    MonitorSystemModel.id == item.id).first()
                if not res:
                    continue
                res.is_delete = 0
                res.uuid = uuid.uuid1().hex
                res.host = item.host
                res.path = item.path
                res.protocol = item.protocol
                new_dt = item.create_at[:19]
                res.create_at = datetime.strptime(new_dt, "%Y-%m-%d %H:%M:%S")
                res.update_at = datetime.strptime(new_dt, "%Y-%m-%d %H:%M:%S")
                db.session.flush()
            db.session.commit()

            result = db.session.query(MyModel).filter().all()
            for item in result:
                # print(item[3])
                # 查找app，更新download_url
                # app = AppModel.query.filter(AppModel.create_at >= datetime.strptime(item[6], "%Y-%m-%d %H:%M:%S.%f"), AppModel.create_at <= datetime.strptime(item[6], "%Y-%m-%d %H:%M:%S.%f") - timedelta(secondsd=2)).all()
                print("====>", item.create_at, (datetime.strptime(
                    item.create_at, "%Y-%m-%d %H:%M:%S.%f") + timedelta(seconds=2)).strftime("%Y-%m-%d %H:%M:%S"))
                app = AppModel.query.filter(AppModel.create_at >= item.create_at, AppModel.create_at <= (datetime.strptime(
                    item.create_at, "%Y-%m-%d %H:%M:%S.%f") + timedelta(seconds=2)).strftime("%Y-%m-%d %H:%M:%S")).first()
                if not app:
                    continue
                print(app)
                # 再判断是否存在于package中，不存在则插入
                res = db.session.query(PackageModel).filter(
                    PackageModel.file_path == item.app_path).limit(1).one_or_none()
                if res:
                    app.download_url = item.app_path
                    res.app_version = item.app_version
                    db.session.flush()
                else:
                    res = PackageModel(app=app.id, app_version=item.app_version, file_path=item.app_path, package_info=item.app_info, create_at=datetime.strptime(
                        item.create_at, "%Y-%m-%d %H:%M:%S.%f"), create_by=item.create_by, update_at=datetime.strptime(item.create_at, "%Y-%m-%d %H:%M:%S.%f"), update_by=item.create_by)
                    db.session.add(res)
                    db.session.flush()
                    logger.info(res)
                print(item)
            db.session.commit()
            return response_result(ResponseCode.HTTP_SUCCESS)
        except:
            traceback.print_exc()
            return response_result(ResponseCode.HTTP_SERVER_ERROR)

    def post(self):
        self.parser.add_argument(
            "access_key", type=str, location="form", required=True)
        self.parser.add_argument("app_name", type=str,
                                 location="form", required=True)
        self.parser.add_argument(
            "app_version", type=str, location="form", required=True)
        self.parser.add_argument("category", type=str,
                                 location="form", required=True)
        self.parser.add_argument("app_desc", type=str,
                                 location="form", required=False)
        self.parser.add_argument(
            "binfiles", type=FileStorage, location="files", required=True)
        args = self.parser.parse_args()

        try:
            # logger.info(request.host)
            # logger.info(request.host_url)
            # logger.info(request.path)
            # logger.info(request.full_path)

            data = dict()
            for key, value in args.items():
                if value != None:
                    data[key] = value

            if 'binfiles' in request.files:
                files = []
                dt = datetime.now().strftime("%Y%m%d%H%M%S")
                upload_path = Path(config.EPK_DIR).joinpath(
                    args.access_key).joinpath(dt)
                if not upload_path.exists():
                    os.makedirs(upload_path.resolve().as_posix())

                for f in request.files.getlist('binfiles'):
                    file_path = upload_path.joinpath(
                        secure_filename(f.filename))
                    f.save(file_path.resolve().as_posix())
                    files.append(file_path.resolve().as_posix())

                data.update({'host_url': request.host_url})

                result, message = signalManager.actionApplicationBuild.emit(
                    data, files)
                if result:
                    return response_result(ResponseCode.HTTP_SUCCESS, data=result)
                else:
                    return response_result(message)
            else:
                return response_result(ResponseCode.HTTP_INVAILD_REQUEST, msg="files can not be null")
        except Exception as e:
            traceback.print_exc()
            current_app.logger.error(e)
            return response_result(ResponseCode.HTTP_SERVER_ERROR)


class CStringToolResource(Resource):
    def __init__(self):
        # 特殊参数，即不是从json获取参数的接口，可以将这个注释打开
        self.parser = RequestParser()

    def get(self):
        result = {
            "results": [
                {
                    "gender": "female",
                    "name": {
                        "title": "Miss",
                        "first": "Candice",
                        "last": "Gonzales"
                    },
                    "location": {
                        "street": {
                            "number": 3007,
                            "name": "Northaven Rd"
                        },
                        "city": "Warragul",
                        "state": "Queensland",
                        "country": "Australia",
                        "postcode": 6657,
                        "coordinates": {
                            "latitude": "-87.1892",
                            "longitude": "91.2147"
                        },
                        "timezone": {
                            "offset": "-1:00",
                            "description": "Azores, Cape Verde Islands"
                        }
                    },
                    "email": "candice.gonzales@example.com",
                    "login": {
                        "uuid": "253648f6-1ba1-4196-aaf8-0b7a0a7f819b",
                        "username": "lazybear738",
                        "password": "wallet",
                        "salt": "TOehKzxN",
                        "md5": "01f4d04fbbdc7da7145c733e6d6fef77",
                        "sha1": "3c63e0f753b75c4bc141f49c4e8072d945beddc1",
                        "sha256": "102535a2f99c2dee933c1261bd3f70e042c628818a938e97a95391eabe0df252"
                    },
                    "dob": {
                        "date": "1970-03-01T16:04:10.320Z",
                        "age": 51
                    },
                    "registered": {
                        "date": "2013-07-27T18:45:18.202Z",
                        "age": 8
                    },
                    "phone": "06-4951-5747",
                    "cell": "0479-024-688",
                    "id": {
                        "name": "TFN",
                        "value": "046353523"
                    },
                    "picture": {
                        "large": "https://randomuser.me/api/portraits/women/3.jpg",
                        "medium": "https://randomuser.me/api/portraits/med/women/3.jpg",
                        "thumbnail": "https://randomuser.me/api/portraits/thumb/women/3.jpg"
                    },
                    "nat": "AU"
                }
            ],
            "info": {
                "seed": "60ef4c21e9a77500",
                "results": 1,
                "page": 1,
                "version": "1.3"
            }
        }
        return response_result(ResponseCode.HTTP_SUCCESS, data=result)

    @jwt_required(locations=["headers"])
    def post(self):
        self.parser.add_argument(
            "string", type=str, location="json", required=True)
        args = self.parser.parse_args()

        try:
            jwt = get_jwt_identity()
            logger.info(jwt)
            return response_result(ResponseCode.HTTP_SUCCESS, data=convert_string(args.string))
        except ValidationError as e:
            return response_result(ResponseCode.HTTP_INVAILD_REQUEST, data=e.messages)
        except Exception as e:
            data = None
            if hasattr(e, 'args'):
                data = e.args
            current_app.logger.error(e)
            return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data)


class ObfuscatedCode(Resource):
    def __init__(self) -> None:
        super().__init__()
        self.parser = RequestParser()

    def post(self):
        # 特殊参数，即不是从json获取参数的接口，可以将这个注释打开
        # self.parser.add_argument("page", type=int, location="args", default=1)
        self.parser.add_argument(
            "string", type=str, location="json", required=True)
        args = self.parser.parse_args()

        try:
            print(args)

            # fname = "./a.c"
            # target = os.sep.join(["out", fname])

            # if os.path.exists(fname):
            #     os.remove(fname)

            # if os.path.exists(target):
            #     os.remove(target)

            # with open(fname, "w+") as f:
            #     f.write(data['string'])

            # result = os.system("./opqcp {i} ./out".format(i=fname))
            # print(result)

            # with open(target) as f:
            #     result = f.read()

            # return result

            return response_result(ResponseCode.HTTP_SUCCESS)
        except ValidationError as e:
            return response_result(ResponseCode.HTTP_INVAILD_REQUEST, data=e.messages)
        except Exception as e:
            data = None
            if hasattr(e, 'args'):
                data = e.args
            current_app.logger.error(e)
            return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data)

# 获取启动器接口
class LauncherResource(Resource):
    def __init__(self) -> None:
        super().__init__()
        self.parser = RequestParser()

    def post(self):
        # self.parser.add_argument("page", type=int, location="args", default=1)
        self.parser.add_argument(
            "imei", type=str, location="json", required=True)
        args = self.parser.parse_args()

        try:
            data = dict()
            for key, value in args.items():
                if value != None:
                    data[key] = value

            result, message = signalManager.actionGetLauncher.emit(data)
            if result:
                logger.info(result.resolve())
                ret = result.read_bytes()
                # with open(result.resolve().as_posix(), "rb") as f:
                #     ret = f.read()
                return Response(ret, mimetype="text/html", content_type="text/html; charset=utf-8")
            return response_result(message, data=result)
        except ValidationError as e:
            return response_result(ResponseCode.HTTP_INVAILD_REQUEST, data=e.messages)
        except Exception as e:
            traceback.print_exc()
            data = None
            if hasattr(e, 'args'):
                data = e.args
            current_app.logger.error(e)
            return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data)

# 获取App列表接口
class AppListResource(Resource):
    def __init__(self) -> None:
        super().__init__()
        self.parser = RequestParser()

    def get(self):
        try:
            return response_result(ResponseCode.HTTP_SUCCESS)
        except Exception as e:
            current_app.logger.error(e)
            return response_result(ResponseCode.HTTP_SERVER_ERROR)

    def post(self):
        self.parser.add_argument(
            "imei", type=str, location="json", required=False)
        self.parser.add_argument(
            "review", type=int, location="json", default=1, required=False)
        self.parser.add_argument("category", type=str,
                                 location="json", required=False)
        args = self.parser.parse_args()

        try:
            data = dict()
            for key, value in args.items():
                if value != None:
                    data[key] = value

            dataList = None
            result, message = signalManager.actionGetAppList.emit(data)
            if result:
                dataList = []
                # 遍历列表，添加一些额外信息
                for item in result:
                    t = item.to_dict()
                    t.update({'download': random.randint(1, 1000),
                              'like': random.randint(0, 100),
                              'meta_data': json.loads(item.meta_data) if item.meta_data else None})
                    dataList.append(t)
                # result = getListAppsSchema.dumps(result)

            category = [
                {
                    "uuid": 1,
                    "img": "music.png",
                    "title": "音乐",
                    "url": "http://store.evmiot.com/uploads/store/music.png"
                },
                {
                    "uuid": 2,
                    "img": "movie.png",
                    "title": "视频",
                    "url": "http://store.evmiot.com/uploads/store/movie.png"
                },
                {
                    "uuid": 3,
                    "img": "camera.png",
                    "title": "相机",
                    "url": "http://store.evmiot.com/uploads/store/camera.png"
                },
                {
                    "uuid": 4,
                    "img": "voice.png",
                    "title": "语音",
                    "url": "http://store.evmiot.com/uploads/store/voice.png"
                },
                {
                    "uuid": 5,
                    "img": "tool.png",
                    "title": "工具",
                    "url": "http://store.evmiot.com/uploads/store/tool.png"
                }
            ]

            return response_result(message, data=dataList, category=category)
        except ValidationError as e:
            return response_result(ResponseCode.HTTP_INVAILD_REQUEST, data=e.messages)
        except Exception as e:
            traceback.print_exc()
            data = None
            if hasattr(e, 'args'):
                data = e.args
            current_app.logger.error(e)
            return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data)

# 获取应用接口
class App(Resource):
    def __init__(self) -> None:
        super().__init__()
        self.parser = RequestParser()

    def get(self):
        # self.parser.add_argument("page", type=int, location="args", default=1)
        self.parser.add_argument(
            "uuid", type=str, location="args", required=True)
        args = self.parser.parse_args()

        try:
            data = dict()
            for key, value in args.items():
                if value != None:
                    data[key] = value

            result, message = signalManager.actionGetApplication.emit(data)
            if result:
                result = result.to_dict()
                result.update({'download': random.randint(1, 1000),
                               'like': random.randint(0, 100),
                               'timestamp': int(time.time()),
                               'meta_data': json.loads(result["meta_data"])})
            return response_result(message, data=result)
        except ValidationError as e:
            return response_result(ResponseCode.HTTP_INVAILD_REQUEST, data=e.messages)
        except Exception as e:
            traceback.print_exc()
            data = None
            if hasattr(e, 'args'):
                data = e.args
            current_app.logger.error(e)
            return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data)

# 获取应用信息接口
class AppInfo(Resource):
    def __init__(self) -> None:
        super().__init__()
        self.parser = RequestParser()

    # 检查app是否为最新版本
    def get(self):
        self.parser.add_argument(
            "uuid", type=str, location="args", required=True)
        self.parser.add_argument(
            "imei", type=str, location="args", required=True)
        args = self.parser.parse_args()

        try:
            logger.info(args)
            data = dict()
            for key, value in args.items():
                if value != None:
                    data[key] = value

            result, message = signalManager.actionCheckVersion.emit(data)
            if result:
                return {'data': {'status': 1, 'time': int(time.time())}, 'version': None, 'downloadUrl': None}
            return {'data': {'status': 0, 'time': int(time.time())}}
        except ValidationError as e:
            return response_result(ResponseCode.HTTP_INVAILD_REQUEST, data=e.messages)
        except Exception as e:
            data = None
            if hasattr(e, 'args'):
                data = e.args
            current_app.logger.error(e)
            return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data)

# 下载EPK文件接口
class DownloadEpk(Resource):
    def __init__(self) -> None:
        super().__init__()
        self.parser = RequestParser()

    def post(self):
        self.parser.add_argument(
            "byId", type=str, location="json", required=True)
        self.parser.add_argument(
            "uuid", type=str, location="json", required=True)
        self.parser.add_argument(
            "imei", type=str, location="json", required=True)
        args = self.parser.parse_args()

        try:
            print(args)
            data = dict()
            for key, value in args.items():
                if value != None:
                    data[key] = value

            data.update({'real_ip': request.headers.get(
                'X-Forwarded-For', '127.0.0.1')})
            result, message = signalManager.actionGetEpk.emit(data)
            # 读取epk文件，按照格式返回相应结构体数据
            logger.info(data)
            if result:
                ret = result.read_bytes()
                # with open(result.as_posix(), "rb") as f:
                #     ret = f.read()
                #     logger.info(type(ret))
                return Response(ret, content_type="text/html; charset=utf-8")
            return response_result(message, data=result)
        except ValidationError as e:
            return response_result(ResponseCode.HTTP_INVAILD_REQUEST, data=e.messages)
        except Exception as e:
            data = None
            if hasattr(e, 'args'):
                data = e.args
            current_app.logger.error(e)
            return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data)


class DownloadApp(Resource):
    def __init__(self) -> None:
        super().__init__()
        self.parser = RequestParser()

    def get(self):
        # self.parser.add_argument("page", type=int, location="args", default=1)
        self.parser.add_argument(
            "imei", type=str, location="json", required=True)
        args = self.parser.parse_args()

        try:
            print(args)
            return response_result(ResponseCode.HTTP_SUCCESS)
        except ValidationError as e:
            return response_result(ResponseCode.HTTP_INVAILD_REQUEST, data=e.messages)
        except Exception as e:
            data = None
            if hasattr(e, 'args'):
                data = e.args
            current_app.logger.error(e)
            return response_result(ResponseCode.HTTP_SERVER_ERROR, data=data)

class Workbench(Resource):
    def __init__(self) -> None:
        super().__init__()
        self.parser = RequestParser()

    @jwt_required(locations=["headers"])
    def get(self):
        # 特殊参数，即不是从json获取参数的接口，可以将这个注释打开
        # self.parser.add_argument("page", type=int, location="args", default=1)
        self.parser.add_argument("string", type=str, location="json", required=False)
        args = self.parser.parse_args()

        try:
            jwt = get_jwt_identity()
            result, message = signalManager.actionWorkbench.emit(jwt)
            return response_result(message, data=result)
        except Exception as e:
            traceback.print_exc()
            current_app.logger.error(e)
            return response_result(ResponseCode.HTTP_SERVER_ERROR)