'''
Author: your name
Date: 2021-07-19 14:29:33
LastEditTime: 2021-07-20 17:32:55
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
from pathlib import Path
from datetime import datetime
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.config import config
from application.signal_manager import signalManager
from models.app import postAppSchema, deleteAppSchema, getListAppSchema, getListAppsSchema, getAppSchema
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 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:
            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())

                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()

    @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:
                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:
            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", 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)})
                    dataList.append(t)
                # result = getListAppsSchema.dumps(result)

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

            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)