from uuid import uuid4
import uuid
from flask import jsonify
import json
#import ecal.core.core as ecal_core
#from proto_messages.RTService_pb2 import RTService as rts1
#import proto_messages.RTService_pb2 as RTServicepb
from vrpmdvdeletemoncmd import VRPMDV_DeleteMonCmd
from vrpmdvdeletemonschema import VRPMDV_DeleteMonSchema
from vrpmdvntlink import trySend

# from vrpmdvmonitoringschema import VRPMDV_MonitoringSchema
# from vrpmdvmonitoring  import VRPMDV_Monitoring 

from vrpmdvmonitoringschema import VRPMDV_MonitoringSchema
from vrpmdvmonitoring import VRPMDV_Monitoring
from vrpmdvmonreqschema import VRPMDV_MonReqSchema
from vrpmdvcreatemoncmd import VRPMDV_CreateMonCmd
from vrpmdvcreatemonschema import VRPMDV_CreateMonSchema 
from extensions.rt_service import rt_service as rts
from vrpmdvmonitoringState import VRPMDVMonitoringState
from vrpmdvlogging import createCoproLoggingTask 
import logging


class VRPMDV_Data:   

    def __init__(self):
        #self.loaded = False
        format = "%(asctime)s: %(message)s"
        logging.basicConfig(format=format, level=logging.INFO, datefmt="%H:%M:%S")
        self.mons:list = []
        self.rtservice = rts.RT_Service()
        self.rtservice.initCoproFW("home/root/elffile","zephyr_openamp_rsc_table.elf")
        self.logTask = createCoproLoggingTask() 
        self.loaded = self.loadFile()
        #start the monitorings
        self.startMons();
        
        

    def loadFile(self):
        try: 
            with open('./mons.json', 'r') as f:
                fmons = f.read()

                if not fmons:
                    # return no Item
                    return True
                else:
                    # data = json.loads(fmons)
                    schema = VRPMDV_MonitoringSchema(many=True)
                    #res = schema.loads(fmons) # data
                    self.mons = schema.loads(fmons) # .append(res)
                    return True
        except:
            #nothing todo ML we should create a file later the database
            print("file not found")

    def saveFile(self):
        try: 
            with open('./mons.json', 'w') as f:
                schema = VRPMDV_MonitoringSchema()
                result = schema.dumps(self.mons, many=True) 
                f.write(result)
                return True
        except:
            #nothing todo
            print("could not write file")

    def startMons(self):
        try:
            for i, val in enumerate(self.mons):
                if val.status :
                    self.rtservice.startMonitoring(val.samplerate,val.sampleperiod, val.downtime)
        except:
            print("could not start monitorings") 
            


    def findMon(mon):
        return mon

    def getMonitorings(self):
        # 1st time read file
        # if not self.loaded :
        #     self.loaded = self.loadFile()
        
        schema = VRPMDV_MonitoringSchema()
        result = schema.dumps(self.mons, many=True)
        return result

    def getMonitoring(self, vrpmid):
        try:
            matched_obj = next(x for x in self.mons if str(x.id) == vrpmid)
        except:
            return "no Item found"
        
        # we find it and we return it
        schema = VRPMDV_MonitoringSchema()
        return schema.dumps(matched_obj)



    def setMonitoring(self, id, request):
        try:
            matched_obj = next(x for x in self.mons if str(x.id) == id)
        except:
            return "no Item found"
        
        if 'name' in request : matched_obj.name = request['name']
        if 'samplerate' in request : matched_obj.samplerate = request['samplerate']
        if 'sampleperiod' in request : matched_obj.sampleperiod = request['sampleperiod']
        if 'downtime' in request : matched_obj.downtime = request['downtime']
        if 'status' in request : 
            matched_obj.setStatus(request['status'])
            if (request['status'] == 'started'):
                logging.info("MainThread: started %s", matched_obj.id)                                                        
                matched_obj.setStatus(self._startMonitoring(matched_obj))
            else :
                logging.info("MainThread: stopped %s", matched_obj.id)                                                        
                matched_obj.setStatus(self._stopMonitoring(matched_obj))

        self.saveFile()

        # we find it and we return it
        schema = VRPMDV_MonitoringSchema()
        return schema.dumps(matched_obj)


    def createMonitoring(self, request):
        id = uuid.uuid4()
        createjson = request.get_json()
        vrpmreq = VRPMDV_MonReqSchema().load(createjson)       
        
        mon = VRPMDV_Monitoring(id, vrpmreq.name, vrpmreq.samplerate, vrpmreq.sampleperiod, vrpmreq.downtime, vrpmreq.status, vrpmreq.owner)
        logging.info("Monitoring %s: starting", str(id))

        # create Monitoring on the realtime side 
        if (vrpmreq.status == 'started'): 
            mon.setStatus(self._createMonOnDevice(mon))

        self.mons.append(mon)
        #save to file
        self.saveFile()
        #create result Object in json
        schema = VRPMDV_MonitoringSchema()
        return schema.dumps(mon) 


    def deleteMonitoring(self, vrpmid):
        # if not self.loaded :
        #     self.loaded = self.loadFile()

        # find monitoring with uuid
        #result = filter(lambda mon: str(mon.uuid) == vrpmid["uuid"], self.mons)
        try:
            matched_obj = next(x for x in self.mons if str(x.id) == vrpmid)
        except:
            return "no Item found"
        

        # we find it, delete on realtime side and now remove from list
        #matched_obj.deleteMonitoring()
        self.mons.remove(matched_obj)
        #save the list
        self.saveFile()
        #make result
        schema = VRPMDV_MonitoringSchema()
        return schema.dump(matched_obj)


# internal helper function

    def _createMonOnDevice(self, monitoring):

        #call the start API of the c++ driver
        try:
            vrpmdCreateCmd = VRPMDV_CreateMonCmd(1, monitoring.no , monitoring.samplerate, monitoring.sampleperiod, monitoring.downtime, monitoring.status)
            schemaCreateCmd = VRPMDV_CreateMonSchema() 
            
            trySend(schemaCreateCmd.dumps(vrpmdCreateCmd))
            monitoring.startMonitoring()
            # set status if we have a success TODO
        except:
            return "stopped"
        return "started"


    def _stopMonitoring(self, monitoring):
        #call the stop API of the c++ driver
        try:
            logging.info("MainThread: stop monitoring")
            vrpmdDeleteCmd = VRPMDV_DeleteMonCmd(2, monitoring.id)
            schemaDeleteCmd = VRPMDV_DeleteMonSchema() 
            
            trySend(schemaDeleteCmd.dumps(vrpmdDeleteCmd))
            monitoring.stopMonitoring()            
            logging.info("MainThread: stop monitoring done")            

        except:
            return "no Item found"

        return monitoring.status


# old impl ML
#
    # def createMonitoring(self, request):
    #     id = uuid.uuid4()

    #     createjson = request.get_json()
    #     vrpmreq = VRPMDV_MonReqSchema().load(createjson)
    #     vrpmdCreateCmd = VRPMDV_CreateMonCmd(1, id , vrpmreq.samplerate, vrpmreq.sampleperiod, vrpmreq.downtime, vrpmreq.status)
    #     schemaCreateCmd = VRPMDV_CreateMonSchema() 

    #     valstr = schemaCreateCmd.dumps(vrpmdCreateCmd)
    #     trySend(schemaCreateCmd.dumps(vrpmdCreateCmd))
        
    #     mon = VRPMDV_Monitoring(id, vrpmreq.name, vrpmreq.samplerate, vrpmreq.sampleperiod, vrpmreq.downtime, vrpmreq.status, vrpmreq.owner)
    #     logging.info("Monitoring %s: starting", str(id))
    #     mon.startMonitoring()

    #     self.mons.append(mon)
    #     #save to file
    #     self.saveFile()
    #     #create result Object in json
    #     schema = VRPMDV_MonitoringSchema()
    #     return schema.dumps(mon) 




    # def createMonitoring(self, request):
    #     id = uuid.uuid4()

    #     createjson = request.get_json()
    #     vrpmreq = VRPMDV_MonReqSchema().load(createjson)
    #     vrpmdCreateCmd = VRPMDV_CreateMonCmd(1, id , vrpmreq.samplerate, vrpmreq.sampleperiod, vrpmreq.downtime, vrpmreq.status)
    #     schemaCreateCmd = VRPMDV_CreateMonSchema() 

    #     valstr = schemaCreateCmd.dumps(vrpmdCreateCmd)
    #     trySend(schemaCreateCmd.dumps(vrpmdCreateCmd))
        
    #     mon = VRPMDV_Monitoring(id, vrpmreq.name, vrpmreq.samplerate, vrpmreq.sampleperiod, vrpmreq.downtime, vrpmreq.status, vrpmreq.owner)
    #     logging.info("Monitoring %s: starting", str(id))
    #     mon.startMonitoring()

    #     self.mons.append(mon)
    #     #save to file
    #     self.saveFile()
    #     #create result Object in json
    #     schema = VRPMDV_MonitoringSchema()
    #     return schema.dumps(mon) 


    # def deleteMonitoring(self, vrpmid):
    #     # if not self.loaded :
    #     #     self.loaded = self.loadFile()

    #     # find monitoring with uuid
    #     #result = filter(lambda mon: str(mon.uuid) == vrpmid["uuid"], self.mons)
    #     try:
    #         matched_obj = next(x for x in self.mons if str(x.id) == vrpmid)
    #     except:
    #         return "no Item found"
        

    #     # we find it, delete on realtime side and now remove from list
    #     #matched_obj.deleteMonitoring()
    #     self.mons.remove(matched_obj)
    #     #save the list
    #     self.saveFile()
    #     #make result
    #     schema = VRPMDV_MonitoringSchema()
    #     return schema.dump(matched_obj)


    # def startMonitoring(self, vrpmid):
    #     # if not self.loaded :
    #     #    self.loaded = self.loadFile()

    #     #call the start API of the c++ driver
    #     try:
    #         matched_obj = next(x for x in self.mons if str(x.id) == vrpmid)

    #     except:
    #         return "no Item found"

    #     if matched_obj.startMonitoring() :
    #         #TODO ML return the state
    #         return "started"

    #     return "created"

    # def stopMonitoring(self, vrpmid):
    #     # if not self.loaded :
    #     #    self.loaded = self.loadFile()

    #     #call the stop API of the c++ driver
    #     try:
    #         matched_obj = next(x for x in self.mons if str(x.id) == vrpmid)
    #         logging.info("MainThread: stop monitoring starting")
    #         vrpmdDeleteCmd = VRPMDV_DeleteMonCmd(2, matched_obj.id)
    #         schemaDeleteCmd = VRPMDV_DeleteMonSchema() 
    #         valstr = schemaDeleteCmd.dumps(vrpmdDeleteCmd)
    #         trySend(schemaDeleteCmd.dumps(vrpmdDeleteCmd))
    #         logging.info("MainThread: stop monitoring done")            

    #     except:
    #         return "no Item found"

    #     matched_obj.stopMonitoring()
    #     return matched_obj.monstate.name


    def setStatus(self, id, vrpmStatus):
        if 'status' in vrpmStatus :
            # matched_obj = self.findMonitoring(id)
            #call the start API of the c++ driver
            if (vrpmStatus['status'] == 'started'):
                return self.startMonitoring(id)
            else :
                return self.stopMonitoring(id)

        #     return matched_obj.status
        
        # return ""

    def findMonitoring(self, id):
        try:
            return next(x for x in self.mons if str(x.id) == id)
        except:
            return "no Item found"
    
