import os
import simplejson as json
import time
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from django.views.generic.base import View

from Ansjer.config import BASE_DIR, SERVER_DOMAIN
from Model.models import Equipment_Version, EquipmentVersionLimitModel, CountryIPModel
from Object.RedisObject import RedisObject
from Object.ResponseObject import ResponseObject
from Object.TokenObject import TokenObject
from Object.UrlTokenObject import UrlTokenObject
from Service.CommonService import CommonService
from Service.ModelService import ModelService
from django.db.models import Q
'''
http://192.168.136.45:8077/equipment/OTA?token=test&operation=query&page=1&line=10
http://192.168.136.45:8077/equipment/OTA?token=test&operation=find&page=1&line=10&content={}
http://192.168.136.40:8077/equipment/OTA?eid=138001524641441203480138000&token=test&operation=delete
http://192.168.136.40:8077/equipment/OTA?eid=138001524641441203480138000&token=test&operation=update&status=1
https://cdna.artstation.com/p/assets/images/images/004/727/674/large/daniel-dociu-snowcavels.jpg?1485828233&dl=1
https://cdna.artstation.com/p/assets/images/images/004/693/910/large/daniel-dociu-smoothsailing.jpg?1485560128&dl=1
'''


class EquipmentOTA(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super(EquipmentOTA, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        return self.validation(request_dict=request.GET)

    def post(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        return self.validation(request_dict=request.POST)

    def validation(self, request_dict, *args, **kwargs):
        token = request_dict.get('token', None)
        response = ResponseObject()
        if token is None:
            return response.json(309)
        tko = TokenObject(token)
        response.lang = tko.lang
        if tko.code != 0:
            return response.json(tko.code)
        userID = tko.userID
        if userID is None:
            return response.json(309)
        operation = request_dict.get('operation', None)
        if operation == 'delete':
            return self.delete(request_dict, userID, response)
        elif operation == 'query':
            return self.query(request_dict, userID, response)
        elif operation == 'find':
            return self.find(request_dict, userID, response)
        elif operation == 'update':
            return self.update(request_dict, userID, response)
        else:
            return response.json(444, 'operation')

    def delete(self, request_dict, userID, response):
        eid = request_dict.get('eid', None)
        version = request_dict.get('version', None)
        if not eid or not version:
            return response.json(444, 'eid or version')
        own_perm = ModelService.check_perm(userID=userID, permID=230)
        if not own_perm:
            return response.json(404)
        equipment_version = Equipment_Version.objects.filter(eid=eid, version=version)
        if not equipment_version.exists():
            return response.json(173)
        try:
            # 删除文件和相应数据
            file_path = equipment_version[0].filePath
            file_path = os.path.join(BASE_DIR, file_path).replace('\\', '/')
            os.remove(file_path)
            equipment_version.delete()
        except Exception as e:
            return response.json(176, repr(e))
        else:
            return response.json(0)

    def query(self, request_dict, userID, response):
        page = int(request_dict.get('page', None))
        line = int(request_dict.get('line', None))
        lang = request_dict.get('lang', None)
        if page is None or line is None:
            return response.json(444, 'page,line')
        own_permission = ModelService.check_perm(userID=userID, permID=240)
        if own_permission is not True:
            return response.json(404)
        if lang is None:
            qs = Equipment_Version.objects.all().order_by('-data_joined')
        else:
            qs = Equipment_Version.objects.filter(lang=lang).order_by('-data_joined')
        if qs.exists():
            count = qs.count()
            res = qs[(page - 1) * line:page * line]
            send_json = CommonService.qs_to_dict(res)
            send_json['count'] = count
            return response.json(0, send_json)
        return response.json(0)

    def find(self, request_dict, userID, response):
        page = int(request_dict.get('page', None))
        line = int(request_dict.get('line', None))
        content = request_dict.get('content', None)
        if page is None or line is None or content is None:
            return response.json(444)
        own_permission = ModelService.check_perm(userID=userID, permID=250)
        if own_permission is not True:
            return response.json(404)
        content = json.loads(content)
        search_kwargs = CommonService.get_kwargs(data=content)
        qs = Equipment_Version.objects.filter(**search_kwargs)
        if not qs.exists():
            return response.json(0, [])
        count = qs.count()
        res = qs[(page - 1) * line:page * line]
        send_json = CommonService.qs_to_dict(res)
        send_json['count'] = count
        return response.json(0, send_json)

    def update(self, request_dict, userID, response):
        eid = request_dict.get('eid', None)
        if eid is None:
            return response.json(444, 'eid')
        own_permission = ModelService.check_perm(userID=userID, permID=230)
        if own_permission is not True:
            return response.json(404)
        ev = Equipment_Version.objects.filter(eid=eid)
        if not ev.exists():
            return response.json(10, 'ev none')
        status = request_dict.get('status', None)
        try:
            update_time = timezone.localtime(timezone.now())
            ev.update(status=status, update_time=update_time)
        except Exception as e:
            print(repr(e))
            pass
        else:
            return response.json(0, {'update_time': str(update_time)})


class EquipmentVersionView(View):
    def get(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        operation = kwargs.get('operation')
        return self.validation(request.GET, operation, request)

    def post(self, request, *args, **kwargs):
        request.encoding = 'utf-8'
        operation = kwargs.get('operation')
        return self.validation(request.POST, operation, request)

    def validation(self, request_dict, operation, request):
        response = ResponseObject()
        if operation is None:
            return response.json(444, 'error path')
        elif operation == 'checkVer':
            return self.do_check_value(request_dict, response)
            # return self.do_check_ver(request_dict, response)

        token = request_dict.get('token', None)
        # 设备主键uid
        tko = TokenObject(token)
        response.lang = tko.lang
        if tko.code != 0:
            return response.json(tko.code)
        userID = tko.userID
        own_perm = ModelService.check_perm(userID, 240)
        if own_perm is False:
            return response.json(404)
        if operation == 'query':
            return self.do_query(request_dict, response)
        if operation == 'update':
            return self.do_update(request_dict, response, request)
        if operation == 'filter':
            return self.do_filter(request_dict, response)
        else:
            return response.json(444, 'error path')

    def do_update(self, request_dict, response, request):
        code = request_dict.get('code', None)
        status = request_dict.get('status', None)
        lang = request_dict.get('lang', None)
        max_ver = request_dict.get('max_ver', None)
        file_s = request.FILES.get('file', None)
        paths = 'static/versions/image'
        if not os.path.exists(paths):
            os.makedirs(paths)  # makedirs 创建文件时如果路径不存在会创建这个路径
            # print ('该文件不存在')
        else:
            print('该文件存在')
        ev = Equipment_Version.objects.filter(code=code, lang=lang)
        if file_s is None:
            rv_path = 'static/versions/image/' + code + '.png'
            img = SERVER_DOMAIN + 'sysfile/' + rv_path
        else:
            rv_path = 'static/versions/image/' + code + '.png'
            try:
                as_path = os.path.join(BASE_DIR, rv_path)
                if os.path.exists(as_path):
                    os.remove(as_path)
                with open(as_path, 'wb+') as destination:
                    for chunk in file_s.chunks():
                        destination.write(chunk)
            except Exception as e:
                pass
            else:
                img = SERVER_DOMAIN + 'sysfile/' + rv_path
        if code is not None:

            if ev.exists():
                try:
                    update_time = timezone.localtime(timezone.now())
                    update_dict = {
                        'status': status,
                        'img': img,
                        'update_time': update_time
                    }
                    if max_ver:
                        update_dict['max_ver'] = max_ver
                    ev.update(**update_dict)
                except Exception as e:
                    return response.json(404, repr(e))
                else:
                    return response.json(0, {'update_time': str(update_time), 'img': img})
            else:
                return response.json(173)
        else:
            return response.json(444, 'code')

    def do_check_ver(self, request_dict, response):
        code = request_dict.get('code', None)
        ov = request_dict.get('ov', None)
        uid = request_dict.get('uid', '')
        if not code:
            return response.json(444, 'code')
        eqs = Equipment_Version.objects.filter(code=uid, status=1, lang='en').order_by('-data_joined')
        if not eqs.exclude():
            eqs = Equipment_Version.objects.filter(code=code, status=1, lang='en').order_by('-data_joined')
        if not eqs.exists():
            return response.json(900)
        if ov is not None:
            # 判断大小
            if ov > eqs[0].softwareVersion:
                return response.json(0, {'softwareVersion': ov})
        file_path = eqs[0].filePath
        if file_path.find('static/Upgrade/') != -1:
            path = file_path.replace('static/Upgrade/', '').replace('\\', '/')
            url = SERVER_DOMAIN + 'OTA/downloads/' + path + '?time=' + str(time.time())
        elif file_path.find('static/otapack') != -1:
            url = SERVER_DOMAIN + 'OTA/downloadsPack/' + file_path + '?time=' + str(time.time())
            # url = SERVER_DOMAIN + 'dl/otaPack/' + file_path + '?time=' + str(time.time())
        else:
            return response.json(900, '2')
        res = {
            "url": url,
            "fileSize": eqs[0].fileSize,
            "Description": eqs[0].Description,
            "softwareVersion": eqs[0].softwareVersion
        }
        return response.json(0, res)

    # 修改加密的路径
    def do_check_value(self, request_dict, response):
        code = request_dict.get('code', None)
        ov = request_dict.get('ov', None)
        uid = request_dict.get('uid', '')
        if not code:
            return response.json(444, 'code')
        eqs = Equipment_Version.objects.filter(code=uid, status=1, lang='en').order_by('-data_joined')

        if not eqs.exclude():
            eqs = Equipment_Version.objects.filter(code=code, status=1, lang='en').order_by('-data_joined')
        if not eqs.exists():
            return response.json(900)
        if ov is not None:
            # 判断大小
            if ov > eqs[0].softwareVersion:
                return response.json(0, {'softwareVersion': ov})
        equipment = eqs[0]
        redisObject = RedisObject()
        key = 'limit_{eid}'.format(eid=equipment.eid)

        evl_qs = redisObject.get_data(key=key)
        if evl_qs:
            evl_qs = json.loads(evl_qs)
        else:
            evl_qs = EquipmentVersionLimitModel.objects.filter(equipment_version_id=equipment.eid, status=1).values()
            if evl_qs.exists():
                redisObject.set_data(key=key, val=json.dumps(list(evl_qs.values())), expire=600)
        if evl_qs and len(evl_qs) > 0:
            evl = evl_qs[0]
            if evl['type'] == 1:  # uid限制
                uids = json.loads(evl['content'])
                if not uids.__contains__(uid):
                    return response.json(902)
        file_path = eqs[0].filePath
        if file_path.find('static/Upgrade/') != -1:
            path = file_path.replace('static/Upgrade/', '').replace('\\', '/')
            # 创建url的token
            tko = UrlTokenObject()
            path = tko.generate(data={'Url': "ansjer/" + CommonService.RandomStr(6) + "/" + file_path})

            url = SERVER_DOMAIN + 'OTA/downloads/' + path
        elif file_path.find('static/otapack') != -1:
            file_path = file_path
            # 创建url的token
            tko = UrlTokenObject()
            file_path = tko.generate(data={'Url': "ansjer/" + CommonService.RandomStr(6) + "/" + file_path})

            url = SERVER_DOMAIN + 'dlotapack/' + file_path
        else:
            return response.json(900, '2')
        # http: // 192.168.136.39:8000 / EquipmentVersion / checkVer?code = 20D20410010

        res = {
            "url": url,
            "fileSize": eqs[0].fileSize,
            "Description": eqs[0].Description,
            "softwareVersion": eqs[0].softwareVersion
        }
        print(url)
        return response.json(0, res)

    def do_query(self, request_dict, response):
        mci = request_dict.get('mci', None)
        page = request_dict.get('page', None)
        line = request_dict.get('line', None)
        code = request_dict.get('code', None)
        if not page or not line:
            return response.json(444, 'page,line')
        else:
            page = int(page)
            line = int(line)
        cv_qs = Equipment_Version.objects
        if mci is not None:
            cv_qs = cv_qs.filter(mci=mci)
        if code is not None:
            cv_qs = cv_qs.filter(code__contains=code)
        cv_qs = cv_qs.order_by('code').values_list('code', flat=True).distinct()
        print(cv_qs)
        count = cv_qs.count()
        cv_qs = list(cv_qs[(page - 1) * line:page * line])
        # return response.json(0, cv_qs)
        ev_qs = Equipment_Version.objects.filter(code__in=list(cv_qs)).values()
        ev_list = CommonService.qs_to_list(ev_qs)
        datas = {}
        # 组装数据
        for ev in ev_list:
            for code in cv_qs:
                if code not in datas.keys():
                    datas[code] = []
                if code == ev['code']:
                    datas[code].append(ev)
        res = {
            'datas': datas,
            'count': count
        }
        return response.json(0, res)

    def do_filter(self, request_dict, response):
        mci = request_dict.get('mci', None)
        page = request_dict.get('page', None)
        line = request_dict.get('line', None)
        code = request_dict.get('code', None)
        lang = request_dict.get('lang', None)
        if not page or not line:
            return response.json(444, 'page,line')
        else:
            page = int(page)
            line = int(line)
        ev_qs = Equipment_Version.objects
        if mci:
            ev_qs = ev_qs.filter(mci=mci)
        if code:
            ev_qs = ev_qs.filter(code__contains=code)
        if lang:
            if lang == 'cn' or lang == 'zh-Hans':
                ev_qs = ev_qs.filter(Q(lang='cn') | Q(lang='zh-Hans'))
            else:
                ev_qs = ev_qs.filter(lang=lang)

        count = ev_qs.count()
        ev_qs = ev_qs[(page - 1) * line:page * line].values()
        ev_ls = CommonService.qs_to_list(ev_qs)
        res = {
            'datas': ev_ls,
            'count': count
        }
        return response.json(0, res)
