"""
     Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
     Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
     Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>

     Web site: http://www.astronomix.org/trac/Skylive-NG

     This file is part of Skylive-NG.

     Skylive-NG is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     (at your option) any later version.

     Skylive-NG is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with Skylive-NG.  If not, see <http://www.gnu.org/licenses/>.
"""


from Pycard import model, dialog, timer
import os, wx
from skylive import protocol, config 
import downprog
import time
from zipfile import ZipFile as zip
from skylive.lang import language

class Scriptsgui(model.Background):

   def on_initialize(self, event):
      self.initialized=False
      self.verifyFree=False
      self._parent = self.getParent()
      self.teleOn = self._parent.teleOn
      self.writeStatus("Initializing....")
      self.lang = self._parent.lang
      self.gui = 'scriptsgui'
      self.ItemText = language.getItemText
      self.setGui()
      self.srvproto = self._parent.srvproto
      self.telescopeOk = False
      self.actionRequest = False
      self.usrid = config.getUsername()
      self.usrpsw = config.getPassword()
      self.seqNum = 0
      self.fileNum = 0
      self.freeCount = 0
      self.demultiCount = 0
      self.scriptSep = self._parent.scriptSep
      self.eventTimerStart()
      self.initialized=True
      self.setTeleLinkStatus(self._parent.teleOn)
      self.goNextScript()
      self.PhotoRunning = False

   def eventTimerStart(self):
      self.eventTimer = timer.Timer(self.components.clockTimer, -1)
      self.eventTimer.Start(100)
      self.eventTimerRunning = True

   def eventTimerStop(self):
      try:
         self.eventTimer.Stop()
         self.eventTimerRunning = False
         del self.eventTimer
         self.eventTimer = False
      except:
         pass

   def on_close(self, event):
      if self.actionRequest:
         resultQuestion = dialog.messageDialog(self, self.getText('scriptExitWarning1'),  self.getText('scriptExitWarning2'))
         if resultQuestion.accepted:
            self._parent.components.TScopeCombo.enabled = True
            self.actionRequest = False
            self._parent.scriptguiStarted = False
            event.skip()
      else:
         self._parent.components.TScopeCombo.enabled = True
         self._parent.scriptguiStarted = False
         event.skip()


   def on_callback(self, cmd):
      for key in cmd:
         f=getattr(self, 'on_'+key, None)
         if f and callable(f):
            f(cmd[key])

   def updateQueue(self):
      if self.scripts:
         self.components.queue_scripts.text=""
         for script in self.scripts:
            getactionscript = script.split(self.scriptSep)
            if getactionscript[1] == "PHOTO":
               self.components.queue_scripts.appendText(script+"_XXX.fit\n")
            elif getactionscript[1] == "GOTO":
               self.components.queue_scripts.appendText(script+"\n")
            else:
               dialog.alertdialog(self.getText('scriptWarning1'))
               self.close()

   def writeStatus(self, statusTxt=""):
      self.components.ScriptStatusArea.text = statusTxt

   def resetInfoScript(self):
      self.components.ExpArea.text="000"
      self.components.FilterArea.text="X"
      self.components.BinArea.text="X"
      self.components.fileArea.text="/"
      self.components.startnArea.text="0"
      self.components.repeatArea.text="0"
      self.writeStatus(self.getText('scriptStatus1'))
      self.components.GuideArea.checked=False
      self.components.WebArea.checked=False
      self.components.AutoDarkArea.checked=False
      self.components.AutoFlatArea.checked=False

   def extractDataScript(self):
      if self.scripts:
         self.paramScript = {}
         self.scriptData = self.scripts[0].split(self.scriptSep)
         if self.scriptData[1] == "PHOTO":
            self.paramScript = {"type":self.scriptData[1], 
                                "exp":self.scriptData[2], 
                                "filt":self.scriptData[3], 
                                "guide":self.scriptData[4], 
                                "aflat":self.scriptData[5], 
                                "adark":self.scriptData[6], 
                                "web":self.scriptData[7], 
                                "bin":self.scriptData[9], 
                                "startn":self.scriptData[10], 
                                "repeat":self.scriptData[11], 
                                "path":self.scriptData[12] 
                                }
         elif self.scriptData[1] =="GOTO":
            self.paramScript = {"type":self.scriptData[1],
                                "cmd":self.scriptData[2]
                                }

   def updateInfoScript(self):
      self.extractDataScript()
      if self.paramScript["type"] == "PHOTO":
            self.components.ExpArea.text=self.paramScript["exp"]
            self.components.FilterArea.text=self.paramScript["filt"]
            self.components.BinArea.text=self.paramScript["bin"]
            self.components.fileArea.text=self.paramScript["path"]+"_XXX.fit"
            self.components.startnArea.text=self.paramScript["startn"]
            self.components.repeatArea.text=self.paramScript["repeat"]
            if self.paramScript["guide"] == "1":
               self.components.GuideArea.checked=True
            if self.paramScript["aflat"] == "1":
               self.components.AutoFlatArea.checked=True
            if self.paramScript["adark"] == "1":
               self.components.AutoDarkArea.checked=True
            if self.paramScript["web"] == "1":
               self.components.WebArea.checked=True

   def goNextScript(self):
      self.resetInfoScript()
      self.updateQueue()
      self.updateInfoScript()
      self._parent.updateScript()

   def endScript(self):
      self.resetInfoScript()
      self.writeStatus(self.getText('scriptStatus2'))
      self.components.queue_scripts.text=self.getText('scriptStatus3')
      self._parent.updateScript()
      self.actionRequest = False
      self.components.startScript.enabled = False
      self.eventTimerStop()

   def scriptDone(self):
      if self.scripts:
         self.scripts.remove(self.scripts[0])
         if self.scripts:
            self.goNextScript()
         else:
            self.endScript()

   def makeaPhoto(self):
      self.seqNum = 99
      photostring = self.srvproto.makePhoto(exp=self.paramScript["exp"], filter=self.paramScript["filt"], guide=self.paramScript["guide"], bin=self.paramScript["bin"], aflat=self.paramScript["aflat"], adark=self.paramScript["adark"], web=self.paramScript["web"])
      if photostring:
         self._parent.TwistedLoop.sendNetworkData(photostring)
      self.expNumber = self.expNumber + 1
      self.PhotoRunning = True
      self.seqNum = 1

   def runPhotoScript(self):
      self.seqNum = 99        
      self.numExps = int(self.paramScript["repeat"])
      if self.expNumber < self.numExps:
         if self.actionRequest and self.telescopeOk:
            self.seqNum = 0
      else:
         self.seqNum = 0
         self.scriptDone()
         self.startRunScript()

   def on_scriptFitsDownloaded(self, fits):
      self.seqNum = 99
      repeatedFile = False
      numRepeatedFile = 0
      numForRep = -1
      fileFounded = False
      isNum = False
      savingDir, savingFile =os.path.split(self.pathNewFit)
      extSF = os.path.splitext(savingFile)[1]
      fileNameToSave = savingFile
      #
      # This part used to find a filename not already present 
      # in the savingDir need to be rewritten in a better way.
      # If we walk in a very BIG directory, this way of doing things 
      # can be very SLOW. It is better to use a stat() call or something
      # like os.path.isfile() generating something like
      # filename+sequenceNum+'.fit' and checking if a file with this name
      # exists or not, and if exist increment of 1 the sequenceNum and
      # retrying, so, we don't need to walk over all files in the directory.
      #
      for files in os.listdir(savingDir):
         filename, ext = os.path.splitext(files)
         if '(' and ')' in filename[-4:]:
            startRead = False
            numRep = ''
            for ch in filename:
               if ch == '(':
                  startRead = True
               else:
                  if startRead and ch != ')':
                     numRep = numRep+ch
                  elif startRead and ch == ')':
                     startRead = False
                     try:
                        numRepeatedFile = int(numRep)
                        isNum = True
                     except:
                        isNum = False
                        repeatedFile = False
                        
            if isNum:
               repText = '('+str(numRepeatedFile)+')'
               filenameWOrep = filename.replace(repText, '')
               if filenameWOrep == os.path.splitext(savingFile)[0]:
                  repeatedFile = True
                  if numRepeatedFile > numForRep:
                     numForRep = numRepeatedFile
                  fileNameToSave = filenameWOrep+'('+str(numForRep+1)+')'+extSF
                  
         else:
            if filename == os.path.splitext(savingFile)[0] and not repeatedFile:
               fileNameToSave = filename+'(1)'+extSF
               break
            else:
               if not repeatedFile:
                  fileNameToSave = savingFile
      toSave = os.path.normpath(savingDir+'/'+fileNameToSave)
      readFile = zip(fits, 'r')
      fitsData = readFile.read("SkyFrame.fit")
      readFile.close()
      savedFile = open(toSave, 'wb')
      savedFile.write(fitsData)
      savedFile.close()
      self.fileNum = self.fileNum + 1
      self.seqNum = 5
   
   def photoSave(self, fitname, fitnumber):
      self.seqNum = 99
      if self.components.WebArea.checked:
         self._parent.TwistedLoop.scriptGetFitFile(self._parent.telescopesel)
         self.pathNewFit = os.path.normpath(fitname+"_"+str(fitnumber).zfill(3)+".fit")
         self.writeStatus("Saving "+self.pathNewFit)
         self.seqNum = 4
         
      else:
         self.writeStatus(self.getText('scriptStatus10'))
         self.seqNum = 5

   def runGotoScript(self):
      if self.actionRequest and self.telescopeOk:
         self.seqNum = 0
   
   def sendGotocmd(self):
      self.seqNum = 99
      pointstring = self.usrid+"#^#"+self.usrpsw+"#^#"+"COMANDO#^#"+self.paramScript["cmd"]+"#^#NULL"
      self._parent.TwistedLoop.sendNetworkData(pointstring)
      self.seqNum = 1

   def startRunScript(self):
      if self.scripts:
         if self.paramScript["type"] == "PHOTO":
              self.expNumber = 0
              self.fileNum = int(self.paramScript["startn"])
              self.runPhotoScript()
         if self.paramScript["type"] == "GOTO":
              self.runGotoScript()
      else:
         self.actionRequest = False
         self._parent.components.TScopeCombo.enabled = True

   def on_pauseScript_mouseClick(self, event):
      if self.eventTimerRunning:
         self.eventTimerStop()
         self.components.clockTimer.text = self.getText('stoppedScript')
         self.components.pauseScript.label = self.getText('restartScript')
      else:
         self.eventTimerStart()
         self.components.pauseScript.label = self.getText('pauseScript')
      event.skip()
      
   def on_startScript_mouseClick(self, event):
      self.actionRequest = True
      self._parent.TwistedLoop.sendNetworkData(self.srvproto.sendTeleStatus())
      
   
   def getText(self, item):
      return self.ItemText(self.lang, self.gui, item)
   
   def setGui(self):
      self.title = self.getText('title')
      self.components.pauseScript.label = self.getText('pauseScript')
      self.components.startScript.label = self.getText('startScript')
      self.components.SGstatusBox.label = self.getText('SGstatusBox')
      self.components.nExpTXT.text = self.getText('nExpTXT')
      self.components.pathTXT.text = self.getText('pathTXT')
      self.components.guideTXT.text = self.getText('guideTXT')
      self.components.filterTXT.text = self.getText('filterTXT')
      self.components.expTXT.text = self.getText('expTXT')
      self.components.startNTXT.text = self.getText('startNTXT')
      self.components.runningBox.label = self.getText('runningBox')
      self.components.queueBox.label = self.getText('queueBox')

   def enableAll(self, msg):
      self.components.startScript.enabled = True
      self.writeStatus(msg)
      
   
   def disableAll(self, msg):
      self.components.startScript.enabled = False
      self.writeStatus(msg)
   
   def setTeleLinkStatus(self, status):
      if status:
         if self._parent.domeisopen:
            self.enableAll(self.getText('telestatus1'))
            
         else:
            self.disableAll(self.getText('telestatus2'))
            
      else:
         if self._parent.domeisopen:
            self.disableAll(self.getText('telestatus3'))

            
         else:
            self.disableAll(self.getText('telestatus4'))
      self._parent.TwistedLoop.sendNetworkData(self.srvproto.sendTeleStatus())
   
   def on_TeleLink(self, stat):
      if stat == 'TeleON':
         self.setTeleLinkStatus(True)
         self.teleOn = True

      elif stat =='TeleOFF':
         self.setTeleLinkStatus(False)
         self.teleOn = False
         self.telescopeOk = False
   
   def on_TeleStatus(self, stat):
      if stat == 'Busy' and self.teleOn and not self.actionRequest:
         self.telescopeOk = False
         self.disableAll(self.getText('telestatus5')) #tele occupato
         self.startVerifyFree()
         
      elif stat == 'Free' and self.teleOn and not self.actionRequest:
         self.enableAll(self.getText('telestatus6'))
         if self.verifyFree:
            self.verifyFree=False
      
      elif stat == 'Free' and self.teleOn and self.actionRequest and not self.seqNum == 1:
         self.disableAll(self.getText('telestatus7'))
         self.telescopeOk = True
         self.startRunScript()
      
      elif stat == 'Busy' and not self.teleOn:
         self.telescopeOk = False
         self.disableAll(self.getText('telestatus4'))
      
      elif stat == 'Busy' and self.paramScript["type"] == "GOTO" and self.seqNum == 1:
         self.freeCount = 0
         self.writeStatus(self.getText('telestatus8'))
      
      elif stat == 'Free' and self.paramScript["type"] == "GOTO" and self.seqNum == 1:
         self.writeStatus(self.getText('telestatus9'))
         self.freeCount += 1
         if self.freeCount == 11:
            self.scriptDone()
            self.startRunScript()
    
   def on_clockTimer_timer(self, event):
      self.components.clockTimer.text = time.strftime('%H:%M:%S')
      self.timedEvent()
      event.skip()
   
   def timedEvent(self):
      if self.demultiCount == 0:
         self.demultiCount = 1
         now=time.time()
         try:
            if self.telescopeOk:
               if self.actionRequest and self.paramScript["type"] == "PHOTO":
                  if self.seqNum == 0:
                     self.makeaPhoto()
   
                  if self.seqNum == 1:
                     self.writeStatus(self.getText('scriptStatus7a')+str(self.expNumber)+self.getText('scriptStatus7b')+str(self.numExps))
                     self.seqNum = 99
   
                  if self.seqNum == 2:
                     self.writeStatus(self.getText('scriptStatus8'))
                     self.seqNum = 99
   
                  if self.seqNum == 3:
                     self.photoSave(self.paramScript["path"], self.fileNum)
   
                  if self.seqNum == 5:
                     self.runPhotoScript()
   
               if self.actionRequest and self.paramScript["type"] == "GOTO":
                  if self.seqNum == 0:
                     self.sendGotocmd()
                  if self.seqNum == 1:
                     self._parent.TwistedLoop.sendNetworkData(self.srvproto.sendTeleStatus())
   
            if self.verifyFree:
               if self.countVF < self.limitVF:
                  self.countVF += 1
               else:
                  self._parent.TwistedLoop.sendNetworkData(self.srvproto.sendTeleStatus())
                  self.countVF = 0

            if self.PhotoRunning:
               self._parent.TwistedLoop.sendNetworkData(self.srvproto.sendPhotoRunning(self.actualtel))
         except:
            pass
      elif self.demultiCount in range (1, 10):
         self.demultiCount += 1
      if self.demultiCount == 10:
         self.demultiCount = 0

    
   def on_photoStatus(self, stat):
      if self.actionRequest:
         if stat == 'notReady':
            self.seqNum = 2
         elif stat == 'Ready':
            self.PhotoRunning = False
            self.seqNum = 3
   
   def startVerifyFree(self):
      self.verifyFree=True
      self.countVF = 0
      self.limitVF = 6
      

