import os
import json
import time
import requests
import pandas as pd
from azure.iot.device import IoTHubDeviceClient

# COMMON CONSTANTS
TIME_INTERVAL = 0
DATA_KEY = "data"
MACHINE = "Machine"
EQUIPMENT = "Equipment"
TAG_ID_KEY = "Tag ID"
TAG_HIERARCHY_KEY = "Tag hierarchy"
PARAMETER_NAME_KEY = "Parameter Name"
EXCEL_FILE_PATH = "Data/Kairos/kairos_tags_data.xlsx"
CSV_DATA_FINAL = "Data/Kairos/kairos_iot_hub_data.csv"
VAL_KEY = "val"
DQ_KEY = "dq"
TA_KEY = "ta"
TH_KEY = "th"

# Connection Parameters
CONNECTION_STRING = "HostName=utpod-iot-001.azure-devices.net;" \
                    "DeviceId=edgedevice002;" \
                    "SharedAccessKey=N5H0QoFxylvM8NVkI8XOdjFCrCoNjxVRhF+64TWVTtY="


class KairosDataPush:
    def __init__(self):
        self.tags_list = None
        self.kairos_metrics = {
            "metrics": [
                {
                    "tags": {
                        "c3": self.tags_list
                    },
                    "name": "project_390__ilens.live_data.raw",
                    "group_by": [
                        {
                            "name": "tag",
                            "tags": [
                                "c3"
                            ]
                        }
                    ],
                    "aggregators": [
                        {
                            "name": "sum",
                            "sampling": {
                                "value": "1",
                                "unit": "milliseconds"
                            },
                            "align_sampling": True
                        }
                    ]
                }
            ],
            "plugins": [],
            "cache_time": 0,
            "time_zone": "Asia/Calcutta",
            "start_relative": {
                "value": "45",
                "unit": "hours"
            }
        }
        self.kairos_url = "https://staging.unifytwin.com/kairos/api/v1/" \
                          "datapoints/query"
        self.header = {
            'Authorization': 'Basic aUxlbnM6aUxlbnNTVEckNDU2',
            'Content-Type': 'application/json'}
        self.mapping_json = dict()

    def reading_csv_excel_file(self, csv_excel_path):
        """
        return: return tag_list from csv file
        """
        tag_sheet_df = None
        try:
            # Creating dataframe from excel path
            if ".csv" in csv_excel_path:
                tag_sheet_df = pd.read_csv(csv_excel_path)
            elif ".xlsx" in csv_excel_path:
                tag_sheet_df = pd.read_excel(csv_excel_path)
                self.tags_list = [each_tags for each_tags in tag_sheet_df[TAG_ID_KEY]]

                # Creating mapping json for fetching parameter name and tag hierarchy
                for each_tag_rows in range(len(tag_sheet_df)):
                    self.mapping_json[tag_sheet_df.loc[each_tag_rows, TAG_ID_KEY]] = {
                        "th": tag_sheet_df.loc[each_tag_rows, TAG_HIERARCHY_KEY],
                        "ta": tag_sheet_df.loc[each_tag_rows, PARAMETER_NAME_KEY]
                    }
        except Exception as err:
            print("Exception in reading_csv_file: ", str(err))
        return self.tags_list, tag_sheet_df

    def getting_kairos_data(self, excel_file_path):
        """
        return:
        """
        data_json = dict()
        column_names = []
        try:
            # Creating kairos metrics
            self.reading_csv_excel_file(csv_excel_path=excel_file_path)

            # Kairos Metrics
            self.kairos_metrics["metrics"][0]["tags"]["c3"] = self.tags_list

            # Request post method to Kairos DB
            response = requests.request("POST",
                                        url=self.kairos_url,
                                        headers=self.header,
                                        data=json.dumps(self.kairos_metrics))

            for each_kairos_data in json.loads(response.text)["queries"][0]["results"]:
                data_json[each_kairos_data["tags"]["c3"][0]] = dict(
                    each_kairos_data["values"])

            for each_tags in self.tags_list:
                if each_tags not in data_json:
                    data_json[each_tags] = dict()

            # Creating Dataframe
            data_json_df = pd.DataFrame(data_json)
            data_json_df = data_json_df.fillna("None")

            column_names = data_json_df.columns.to_list()

            data_json_df.to_csv(CSV_DATA_FINAL)
        except Exception as err:
            print("Exception in iot_hub_data_push: ", str(err))
        return CSV_DATA_FINAL, column_names

    def iot_hub_client_init(self):
        """
        Connection of IoT Hub using connection string
        :return:
        """
        client = None
        try:
            print("Initiating - iot_hub_client_init method")
            client = IoTHubDeviceClient.create_from_connection_string(
                CONNECTION_STRING)
            print("Connected - iot_hub_client_init method")
        except Exception as err:
            print("Exception in iot_hub_client_init: ", str(err))
        return client

    def iot_hub_client_telemetry_sample_run(self, csv_path, column_list):
        """
        IoT Hub device sending periodic messages
        :return:
        """
        try:
            print("START: IoT Hub device data push")

            # Connection to IoT Hub using connection strings
            client = self.iot_hub_client_init()

            tag_list, kairos_data_df = self.reading_csv_excel_file(
                csv_excel_path=csv_path)

            message_counter = 1

            # Iterating over each data in data_sheet
            for each_row_count in range(len(kairos_data_df)):

                # JSON data for IoT Hub
                final_json = {
                    "data": {},
                    "site_id": "site_101",
                    "gw_id": "gw_118",
                    "pd_id": "pd_247",
                    "retain_flag": True,
                    "timestamp": int(kairos_data_df.iloc[each_row_count, 0]),
                    "msg_id": int(message_counter),
                    "ver": 1.2,
                    "a_id": "ilens_device_100",
                    "d_id": "kuJj7HZeeNPQLsfgu82t2w",
                    "p_id": "project_390",
                    "topic": "ilens/monitor/live"
                }
                # Iterating over each tags in tag_sheet
                for each_columns in column_list:
                    data_point = kairos_data_df.loc[each_row_count, each_columns]
                    try:
                        # final JSON with tag values
                        final_json[DATA_KEY][each_columns] = {
                            VAL_KEY: float(data_point),
                            DQ_KEY: 1,
                            TA_KEY: self.mapping_json[each_columns][TA_KEY],
                            TH_KEY: self.mapping_json[each_columns][TH_KEY]
                        }
                    except:
                        if data_point != "None":
                            final_json[DATA_KEY][each_columns] = {
                                VAL_KEY: data_point,
                                DQ_KEY: 1,
                                TA_KEY: self.mapping_json[each_columns][TA_KEY],
                                TH_KEY: self.mapping_json[each_columns][TH_KEY]
                            }
                        else:
                            final_json[DATA_KEY][each_columns] = {
                                VAL_KEY: None,
                                DQ_KEY: 2,
                                TA_KEY: self.mapping_json[each_columns][TA_KEY],
                                TH_KEY: self.mapping_json[each_columns][TH_KEY]
                            }

                # Pushing Data To Cloud
                # client.send_message(json.dumps(final_json))
                print("Message sent: \n{}".format(final_json))

                # Time Frequency for data
                time.sleep(TIME_INTERVAL)
                message_counter += 1

                if message_counter == 1000:
                    message_counter = 1

            # Deleting CSV file
            try:
                print(f"Removing CSV file: {csv_path}")
                os.remove(csv_path)
            except:
                pass

        except KeyboardInterrupt:
            print("STOP: IoT Hub device data push")

# if __name__ == "__main__":
#
#     # Send Telemetry to Cloud
#     telemetry_flag = True
#     while True:
#         # Creating Class Object
#         kairos_data_push_obj = KairosDataPush()
#
#         # Getting Data from Kairos and Creating CSV from the Tag Data
#         csv_excel_path, column_list = kairos_data_push_obj.getting_kairos_data(
#             excel_file_path=EXCEL_FILE_PATH)
#
#         # Iterating over data and pushing to Cloud
#         kairos_data_push_obj.iot_hub_client_telemetry_sample_run(
#             csv_path=csv_excel_path,
#             column_list=column_list)
