'''
Author: your name
Date: 2021-07-19 14:29:33
LastEditTime: 2021-07-20 11:35:45
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 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 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) })
                    dataList.append(t)
                # result = getListAppsSchema.dumps(result)
            return response_result(message, data=dataList)
        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 = getAppSchema.dump(result)
            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()

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

        try:
            logger.info(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)

# 下载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)
