import json
import threading
from random import Random


from FileIO import FileIO

class ZoneManager:
    def __init__(self, systemSettings, fileIO):
        self.random = Random()
        self.systemSettings = systemSettings
        self.fileIO = FileIO
        self.zones = fileIO.loadZones()
        for zone in self.zones:
            zone.setZoneManager(self)
        self.pipeLine = []
        self.piplineMutexLock = threading.Lock()

    def zonesToJSON(self, translater):
        zoneList = []
        for zone in self.zones:
            zoneList.append(zone.toJSON(translater))
        return zoneList

    def pipelineToJSON(self, translater):
        jobList = []
        with self.piplineMutexLock:
            for irrigationJob in self.pipeLine:
                jobList.append(irrigationJob.toJSON(translater))
        return jobList


    def getZone(self, number):
        for zone in self.zones:
            if(zone.number == number):
                return zone

    def addIrrigationJob(self, job):
        with self.piplineMutexLock:
            self.pipeLine.append(job)

    def deleteIrrigationJobByID(self, id):
        i = 0
        with self.piplineMutexLock:
            while i < (len(self.pipeLine)):
                irrigationJob = self.pipeLine[i]
                if(irrigationJob.id == id):
                    self.pipeLine.pop(i)
                    break
                else:
                    i = i + 1

    def deleteIrrigationJobsForZone(self, zone):
        i = 0
        with self.piplineMutexLock:
            while i < (len(self.pipeLine)):
                irrigationJob = self.pipeLine[i]
                if (irrigationJob.zone == zone):
                    self.pipeLine.pop(i)
                else:
                    i = i + 1

    def isAnyZoneBusy(self):
        for zone in self.zones:
            if(zone.state):
                return True
        return False

    def switchZoneState(self, zone, state, duration, instant=False):
        if(not duration > 0):
            zone.switchState(state=False, duration=0, instant=True)
        elif(instant or self.systemSettings.multiZoneIrrigation or state==False ): #or (not self.isAnyZoneBusy())
            zone.switchState(state=state, duration=duration, instant=True)
        else:
            self.addIrrigationJob(IrrigationJob(id=self.random.randint(a=100000000, b=999999999), zone=zone, duration=duration))

    def switchZoneIndexState(self, zoneIndex, state, duration, instant=False):
        zone = self.getZone(zoneIndex)
        self.switchZoneState(zone, state, duration, instant)

    def getPlanedDurationForZone(self, zone):
        totalDuration = 0
        with self.piplineMutexLock:
            for irrigationJob in self.pipeLine:
                if(irrigationJob.zone == zone):
                    totalDuration = totalDuration + irrigationJob.duration
        return totalDuration

    def refreshStates(self):
        for zone in self.zones:
            zone.refreshState()

    def processPipeline(self):
        self.piplineMutexLock.acquire()
        index = 0
        while(len(self.pipeLine) > index and (not self.isAnyZoneBusy())):
            irrigationJob = self.pipeLine[index]
            if(not irrigationJob.zone.setState == 1):
                self.pipeLine.pop(index)
                self.piplineMutexLock.release()
                irrigationJob.process()
                return
            else:
                index = index + 1

        self.piplineMutexLock.release()



    def cronJobs(self):
        self.refreshStates()
        self.processPipeline()
        print("Executed Cron Jobs of ZoneManager.")




class IrrigationJob:
    def __init__(self, id, zone, duration=0):
        self.id = id
        self.zone = zone
        self.duration = duration
        self.zone.switchState(state=True, duration=duration, instant=False)

    def toJSON(self, translater):
        return {
            "id": self.id,
            "zone": self.zone.toJSON(translater),
            "duration": self.duration,
        }

    def process(self):
        self.zone.switchState(state=True, duration=self.duration, instant=True)