import ephem
import datetime
import os, sys
import logging

# Dict obj :  {'az': 294:53:36.5, 'result': 'ok', 'hl': 'underHorizon', 'alt':
# -5:38:19.1, 'dec': 23:44:43.1, 'ra': 5:48:58.68}
# hl puo' essere 'ok' se non e' sotto l'orizzonte!

curdir = os.path.abspath(os.path.dirname(sys.argv[0])).replace("/scripts", "").replace("/skyliveDaemon", "")
dbpath = curdir+'/DecraDB/'
long = False
lat = False
obsName = False
horizMap = False
utcdiff = 0
dblist = ['Messier.edb', 'NGC.edb', 'IC.edb', 'YBS.edb']
planetsList = ['Mercury', 'Venus', 'Moon', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune', 'Pluto']

log = logging.getLogger( 'EPHEM' )


class dataSet:
   
   def __init__(self):
      curdir = os.path.abspath(os.path.dirname(sys.argv[0])).replace("/scripts", "").replace("/skyliveDaemon", "")
      self.objdict = {}
      self.long = False
      self.lat = False
      self.obs = False
      self.obsTime = False
      self.utcdiff = 0
      self.dbpath = curdir+'/DecraDB/'
      self.horizMap = False
      self.planetsList =['Mercury', 'Venus', 'Moon', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune', 'Pluto']
      
      dblist = ['Messier.edb', 'NGC.edb', 'IC.edb', 'YBS.edb']
      for db in dblist:
         datab = open(os.path.normpath(self.dbpath+db))
         databR = datab.read()
         datab.close()
         databList = databR.split('\n')
         for databLine in databList:
            if len(databLine) != 0:
               self.objdict[databLine.split(',')[0].replace(' ','').upper()] = databLine
      self.setObsTime()
      self.setObsSite()
   
   def setObsSite(self):
      if self.long and self.lat:
         self.setObsTime()
         obs = ephem.Observer()
         obs.long = self.long
         obs.lat = self.lat
         if self.obsTime:
            obs.date = self.obsTime
            obs.epoch = self.obsTime
            obs.pressure = 0
            obs.altitude = 700
         #obs.epoch = '2000'
         self.obs = obs
      else:
         self.obs = False
   
   def getJ2000(self, reqObj):
      ret = ephem.Equatorial(reqObj, epoch=ephem.J2000)

      return ret

   def getDECRA(self, objReq=False):
      log.info("GET DECRA "+str(objReq))
      if objReq:
         self.setObsTime()
         self.setObsSite()
         try:
            reqObj = ephem.readdb(self.objdict[objReq.upper()])
            if self.obs:
               reqObj.compute(self.obs)
               reqARDEC=self.getJ2000(reqObj)
               if self.horizMap: 
                  ret = {'result':'ok', 'ra':reqARDEC.ra, 'dec':reqARDEC.dec, 'alt':reqObj.alt, 'az':reqObj.az, 'hl':self.verifyHL(reqObj.alt, reqObj.az)}
               else:
                  ret = {'result':'ok', 'ra':reqARDEC.ra, 'dec':reqARDEC.dec, 'alt':reqObj.alt, 'az':reqObj.az, 'hl':'noData'}
            else:
               reqObj.compute()
               reqARDEC=self.getJ2000(reqObj)
               ret = {'result':'okNoObs', 'ra':reqARDEC.ra, 'dec':reqARDEC.dec, 'alt':None, 'az':None, 'hl':None}
         except:
            ret = {'result':'unknow', 'ra':None, 'dec':None, 'alt':None, 'az':None, 'hl':None}
      else:
         ret = {'result':'noObj', 'ra':None, 'dec':None, 'alt':None, 'az':None, 'hl':None}
      log.warning("RESULT FOR DECRA: "+str(ret))
      return ret
   
   def setObsTime(self):
      utcTime = datetime.datetime.utcnow()
      diff = datetime.timedelta(hours=int(self.utcdiff))
      obst = utcTime + diff
      self.obsTime = obst.strftime("%Y/%m/%d %H:%M:%S")
      
      
   def put_obsSite(self, long=False, lat=False, obsNam=False):
      if long and lat:
         self.long = long
         self.lat = lat
         self.setObsTime()
         self.setObsSite()
         
         if obsNam:
            self.searchMap(obsNam)
            
      else:
         self.setObsTime()
         self.setObsSite()
   
   def put_utcDiff(self, utcdiff=0):
      self.utcdiff = utcdiff
   
   def getLandPos(self):
      alt = '0'
      az = '90'
      self.setObsSite()
      if self.obs:
         ra, dec = self.obs.radec_of(az, alt)
         ret = {'ra':ra, 'dec':dec}
      else:
         ret = False
      return ret
   
   def searchMap(self, obsNam):
      mapfile = os.path.normpath(self.dbpath+obsNam)
      if os.path.exists(mapfile) and os.path.isfile(mapfile):
         f = open(mapfile, 'r')
         data = f.read()
         lineData = data.split('\n')
         self.horizMap = {}
         for line in lineData:
            if len(line) > 0:
               deg, altmin, altmax, why = line.split('!')
               self.horizMap[str(deg)] = [str(altmin), str(altmax), why]

   
   def verifyHL(self, alt=False, az=False):
      if alt and az:
         azTC = str(az).split(':')[0]
         altTC = str(alt).split(':')[0]
         if azTC in self.horizMap.keys():
            if int(altTC) in range(int(self.horizMap[azTC][0]), int(self.horizMap[azTC][1])):
               ret = 'ok'
            else:
               if int(altTC) > 0:
                  ret = self.horizMap[azTC][2]
               else:
                  ret = 'underHorizon'
         else:
            if int(altTC) > 0:
               ret = 'ok'
            else:
               ret = 'underHorizon'
         return ret
      else:
         return False
   
   def managePlanetCMD(self, cmd):
      obj = cmd.replace('Pianeta','').replace("PIANETA", "")[4:].lower().capitalize()
      log.debug("Clean Planet: "+str(obj))
      if obj in self.planetsList:
         ret = self.getPlanets(obj)
      else:
         #ret = self.getStar(obj)
         ret = self.getDECRA(obj)
      return ret
   
   def getPlanets(self, planet=False):
      if planet:
         self.setObsTime()
         self.setObsSite()
         if planet == 'Mercury':
            reqObj = ephem.Mercury(self.obs)
         elif planet == 'Venus':
            reqObj = ephem.Venus(self.obs)
         elif planet == 'Moon':
            reqObj = ephem.Moon(self.obs)
         elif planet == 'Mars':
            reqObj = ephem.Mars(self.obs)
         elif planet == 'Jupiter':
            reqObj = ephem.Jupiter(self.obs)
         elif planet == 'Saturn':
            reqObj = ephem.Saturn(self.obs)
         elif planet == 'Uranus':
            reqObj = ephem.Uranus(self.obs)
         elif planet == 'Neptune':
            reqObj = ephem.Neptune(self.obs)
         elif planet == 'Pluto':
            reqObj = ephem.Pluto(self.obs)
         else:
            reqObj = False
            ret = {'result':'unknow', 'ra':None, 'dec':None, 'alt':None, 'az':None, 'hl':None}
         if reqObj:
            reqARDEC=self.getJ2000(reqObj)
            if self.horizMap: 
               ret = {'result':'ok', 'ra':reqARDEC.ra, 'dec':reqARDEC.dec, 'alt':reqObj.alt, 'az':reqObj.az, 'hl':self.verifyHL(reqObj.alt, reqObj.az)}
            else:
               ret = {'result':'ok', 'ra':reqARDEC.ra, 'dec':reqARDEC.dec, 'alt':reqObj.alt, 'az':reqObj.az, 'hl':'noData'}
      else:
         ret = {'result':'noObj', 'ra':None, 'dec':None, 'alt':None, 'az':None, 'hl':None}
      return ret

   def getStar(self, star=False):
      # XXX This is now deprecated in favour of the YBS catalog. See
      # managePlanetCommand
      if star:
         self.setObsTime()
         self.setObsSite()
         try:
            reqObj = ephem.star(star)
            reqObj.compute(self.obs)
            reqARDEC=self.getJ2000(reqObj)
            if self.horizMap: 
               ret = {'result':'ok', 'ra':reqARDEC.ra, 'dec':reqARDEC.dec, 'alt':reqObj.alt, 'az':reqObj.az, 'hl':self.verifyHL(reqObj.alt, reqObj.az)}
            else:
               ret = {'result':'ok', 'ra':reqARDEC.ra, 'dec':reqARDEC.dec, 'alt':reqObj.alt, 'az':reqObj.az, 'hl':'noData'}
         except:
            ret = {'result':'unknow', 'ra':None, 'dec':None, 'alt':None, 'az':None, 'hl':None}
      else:
         ret = {'result':'noObj', 'ra':None, 'dec':None, 'alt':None, 'az':None, 'hl':None}
      return ret
   
   def getAltAzbyRaDec(self, ra=False, dec=False):
      if ra and dec and self.obs:
         cRA, cDEC = self.cleanRADEC(ra, dec)
         self.setObsSite()
         line = "obj,f,"+cRA+","+cDEC+",1,"+self.obsTime[:4]
         posObj = ephem.readdb(line)
         posObj.compute(self.obs)
         ret = {'alt': posObj.alt, 'az': posObj.az}
      else:
         ret = {'alt':None, 'az':None}
      return ret
   
   def cleanRADEC(self, ra, dec):
      cRA = ra.replace('*', ':')
      cDEC = dec.replace('*', ':').replace('.',':')
      return [cRA, cDEC]

dataSearch = dataSet()

def setObsData(long=False, lat=False, obsNam=False):
   if long and lat:
      globals()['long'] = long
      globals()['lat'] = lat
      globals()['obsName'] = obsNam
      
      dataSearch.put_obsSite(long, lat, obsNam)

def setUtcDiff(utcdiff=0):
   globals()['utcdiff'] = utcdiff
   dataSearch.put_utcDiff(utcdiff)
      
def getDECRAbyCMD(obj=False):
   if obj:
      object = obj.upper().replace(' ','')
      if 'CNGC' in object:
         ret = dataSearch.getDECRA(object.replace('CNGC','NGC'))
      elif 'MESSIER' in object:
         ret = dataSearch.getDECRA(object.replace('MESSIER',''))
      elif 'PIANETA' in object:
         ret = dataSearch.managePlanetCMD(obj)
      else:
         ret = False
         if len(object) > 2:
            if 'IC' in object[:2]:
               ret = dataSearch.getDECRA(object.replace('IC', ''))
         if not ret:
            ret = dataSearch.getDECRA()
   return ret

def getDECRAbyLIST(obj=False):
   if obj:
      what, who = obj
      if what.upper() in ['NGC', 'M', 'IC']:
         ret = dataSearch.getDECRA(what.upper()+str(who))
      elif what.upper() == 'PLANET' or what.upper() == 'STAR':
         ret = dataSearch.managePlanetCMD('Pianeta0000'+str(who))
      else:
         ret = dataSearch.getDECRA()
   return ret

def getLandPos():
   return dataSearch.getLandPos()

def getALTAZbyRADEC(ra=False, dec=False):
   if ra and dec:
      ret = dataSearch.getAltAzbyRaDec(ra, dec)
   else:
      ret = False
   return ret


