#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
from abc import ABCMeta,abstractmethod

import boto3

from Ansjer.config import AWS_IOT_SES_ACCESS_CHINA_REGION, AWS_IOT_SES_ACCESS_CHINA_ID, AWS_IOT_SES_ACCESS_CHINA_SECRET, \
    AWS_IOT_SES_ACCESS_FOREIGN_REGION_AMERICA, AWS_IOT_SES_ACCESS_FOREIGN_ID, AWS_IOT_SES_ACCESS_FOREIGN_SECRET, \
    AWS_IOT_SES_ACCESS_FOREIGN_REGION_EUROPE, AWS_IOT_SES_ACCESS_FOREIGN_REGION_ASIA, AWS_IOT_SES_ACCESS_CHINA_ROLE, \
    AWS_IOT_SES_ACCESS_FOREIGN_ROLE


class IOTObject(metaclass=ABCMeta):

    @abstractmethod
    def create_provisioning_claim(self, templateName):
        pass

    @abstractmethod
    def create_keys_and_certificate(self, uid):
        pass


class IOTClient(IOTObject):

    def __init__(self, region_id = 1):

        if region_id == 1:
            self.client = boto3.client('iot', region_name=AWS_IOT_SES_ACCESS_CHINA_REGION,
                                       aws_access_key_id=AWS_IOT_SES_ACCESS_CHINA_ID,
                                       aws_secret_access_key=AWS_IOT_SES_ACCESS_CHINA_SECRET)
            self.endpoint = 'a250bbr0p9u7as-ats.iot.cn-northwest-1.amazonaws.com.cn'
            self.iotrole = AWS_IOT_SES_ACCESS_CHINA_ROLE

        if region_id == 2:
            self.client = boto3.client('iot', region_name=AWS_IOT_SES_ACCESS_FOREIGN_REGION_ASIA,
                                       aws_access_key_id=AWS_IOT_SES_ACCESS_FOREIGN_ID,
                                       aws_secret_access_key=AWS_IOT_SES_ACCESS_FOREIGN_SECRET)
            self.endpoint = 'a2rqy12o004ad8-ats.iot.ap-southeast-1.amazonaws.com'
            self.iotrole = AWS_IOT_SES_ACCESS_FOREIGN_ROLE

        if region_id == 3:
            self.client = boto3.client('iot', region_name=AWS_IOT_SES_ACCESS_FOREIGN_REGION_AMERICA,
                                       aws_access_key_id=AWS_IOT_SES_ACCESS_FOREIGN_ID,
                                       aws_secret_access_key=AWS_IOT_SES_ACCESS_FOREIGN_SECRET)
            self.endpoint = 'a2rqy12o004ad8-ats.iot.us-east-1.amazonaws.com'
            self.iotrole = AWS_IOT_SES_ACCESS_FOREIGN_ROLE

        if region_id == 4:
            self.client = boto3.client('iot', region_name=AWS_IOT_SES_ACCESS_FOREIGN_REGION_EUROPE,
                                       aws_access_key_id=AWS_IOT_SES_ACCESS_FOREIGN_ID,
                                       aws_secret_access_key=AWS_IOT_SES_ACCESS_FOREIGN_SECRET)
            self.endpoint = 'a2rqy12o004ad8-ats.iot.eu-west-1.amazonaws.com'
            self.iotrole = AWS_IOT_SES_ACCESS_FOREIGN_ROLE



    def create_provisioning_claim(self, templateName):

        result = self.client.create_provisioning_claim(templateName=templateName)

        res = {
            'certificateId': result['certificateId'],
            'certificatePem': result['certificatePem'],
            'publicKey': result['keyPair']['PublicKey'],
            'privateKey': result['keyPair']['PrivateKey'],
            'endpoint': self.endpoint
        }
        return res

    def create_keys_and_certificate(self, ThingNameSuffix, thingGroup, response):
        try:
            result = self.client.create_keys_and_certificate(setAsActive=True)
            res = {
                'certificateId': result['certificateId'],
                'certificatePem': result['certificatePem'],
                'publicKey': result['keyPair']['PublicKey'],
                'privateKey': result['keyPair']['PrivateKey'],
                'endpoint': self.endpoint
            }
            # 搜索是否存在该物品组
            thing_groups_res = self.client.list_thing_groups(nextToken='', maxResults=1,
                                                             namePrefixFilter=thingGroup, recursive=False)
            if thing_groups_res['thingGroups']:
                thingGroupName = thing_groups_res['thingGroups'][0]['groupName']  # 获取物品组名称
            else:
                attributes = {
                    "update_time": "0"
                }
                thingGroupProperties = {
                    "thingGroupDescription": "OTA",
                    "attributePayload": {
                        "attributes": attributes,
                        "merge": False  # 更新时覆盖掉而不是合并
                    }
                }
                create_thing_group_res = self.client.create_thing_group(thingGroupName=thingGroup,
                                                                        thingGroupProperties=thingGroupProperties)
                thingGroupName = create_thing_group_res['thingGroupName']  # 获取物品组名称
            print('物品组:', thingGroupName)
            # 根据证书ID注册物品和策略
            templateBody = {
                "Parameters": {
                    "ThingName": {
                        "Type": "String"
                    },
                    "SerialNumber": {
                        "Type": "String"
                    },
                    "thingGroupName": {
                        "Type": "String"
                    },
                    "AWS::IoT::Certificate::Id": {
                        "Type": "String"
                    }
                },
                "Resources": {
                    "thing": {
                        "Type": "AWS::IoT::Thing",
                        "Properties": {
                            "AttributePayload": {},
                            # "ThingGroups" : ["v1-lightbulbs", {"Ref" : "DeviceLocation"}],
                            "ThingName": {
                                "Ref": "ThingName"
                            },
                            "ThingGroups": [{"Ref": "thingGroupName"}]
                        },
                        "OverrideSettings": {
                            "AttributePayload": "MERGE",
                            "ThingTypeName": "REPLACE",
                            "ThingGroups": "DO_NOTHING"
                        }
                    },
                    "certificate": {
                        "Type": "AWS::IoT::Certificate",
                        "Properties": {
                            "CertificateId": {"Ref": "AWS::IoT::Certificate::Id"},
                            "Status": "Active"
                        }
                    },
                    "policy": {
                        "Properties": {
                            "PolicyName": "My_Iot_Policy"
                        },
                        "Type": "AWS::IoT::Policy"
                    },
                }
            }
            ThingName = 'Ansjer_Device_' + ThingNameSuffix
            templateBody = json.dumps(templateBody)
            parameters = {"ThingName": ThingName,
                          "thingGroupName": thingGroupName,
                          "AWS::IoT::Certificate::Id": res['certificateId']}
            self.client.register_thing(
                templateBody=templateBody,
                parameters=parameters
            )
            topicsql = "SELECT * FROM 'my/things/" + ThingName + "/shadow/update_lwt'"
            self.client.create_topic_rule(
                ruleName= ThingName + '_LWT',
                topicRulePayload={
                    "sql": topicsql,
                    "ruleDisabled": False,
                    "awsIotSqlVersion": "2016-03-23",
                    'actions': [
                        {
                            'republish': {
                                'roleArn': self.iotrole,
                                'topic': '$$aws/things/' + ThingName + '/shadow/update',
                                'qos': 1
                            }
                        }
                    ]
                }
            )
            return res, parameters
        except Exception as e:
            print(e)
            return response.json(500, repr(e))
