from twisted.web import resource, static
import cgi, logging
from nevow import rend, tags, loaders, flat, inevow
import os, sys
from skyliveDaemon import calendar
from skyliveDaemon.utils import genutils as utils
import urllib
import time
from utils import timezones
from pytz import common_timezones as wtz
from twisted.internet import threads
from skyliveDaemon.Database import utils as dbutils

log = logging.getLogger("Webgui")
curdir=os.path.abspath(os.path.dirname(sys.argv[0]))
template_path = curdir+'/Web/html/Shared/'


def check_date(y, m, d):
   tup1 = (int(y), int(m), int(d), 0,0,0,0,0,0)
   try:
      date = time.mktime(tup1)
      tup2 = time.localtime(date)
      if tup1[:2] != tup2[:2]:
         return False
      return True
   except OverflowError:
      return False


def splitDate(date):
      y =  date[:4]
      m =  date[4:6]
      d =  date[6:8]
      return y, m, d


def getThreeDays(date, tz=None):
   y, m, d = splitDate(date)
   monthstart, monthstop, month = utils.getMonth(y, m)
   monthdays=month.keys()
   monthdays.sort()
   if int(d) == 1:
      if int(m) == 1:
         yy = str(int(y)-1)
         my = '12'
         dy = '31'
      else:
         yy = str(y)
         my = str(int(m)-1).zfill(2)
         # XXX BUG! tz non lo trova?
         starty, stopy, monthy = utils.getMonth(yy, my, tz)
         monthydays  = monthy.keys()
         monthydays.sort()
         lasty, lastm, dy = splitDate(str(monthydays[-1]))
   else:
      yy = str(y)
      my = str(m).zfill(2)
      dy = str(int(d)-1).zfill(2)
   datey=yy+my+dy
   log.debug('AAA-'+str(date)+'-'+str(monthdays[-1]))
   if int(date) == int(monthdays[-1]):
      if int(m) == 12:
         yt = str(int(y)+1)
         mt = '01'
         dt = '01'
      else:
         yt = y
         mt = str(int(m)+1).zfill(2)
         dt = '01'
   else:
      yt = y
      mt = m
      dt = str(int(d)+1).zfill(2)
   datet=yt+mt+dt
   return datey, datet


def calendarArgs(ctx=None, d=None, l=None, t=None):
   rets = {'date': 'today', 'tz': 'Europe/Rome', 'lang': 'it'}
   date=False
   tz=False
   if ctx:
      if 'date' in ctx.locate(inevow.IRequest).args:
         date = ctx.locate(inevow.IRequest).args['date'][-1]
         if str(date) == 'today':
            date = time.strftime("%Y%m%d", time.gmtime())
      if 'tz' in ctx.locate(inevow.IRequest).args:
         tz = ctx.locate(inevow.IRequest).args['tz'][-1]
      if 'lang' in ctx.locate(inevow.IRequest).args:
         rets['lang'] = ctx.locate(inevow.IRequest).args['lang'][-1]
   if d:
      date = d
   if date:
      if date=='today' or ( len(str(date)) == 8 and  date.isdigit() and
         check_date(str(int(date))[:4], str(int(date))[4:6], str(int(date))[6:8])):
         if date=='today':
            date=time.strftime("%Y%m%d", time.localtime())
         rets['date'] = date
   if t:
      tz=t
   if tz:
      if tz in wtz:
         rets['tz'] = tz
   if l and l in ['it', 'en']:
      rets['lang'] = l

   return {'urlstr': urllib.urlencode(rets), 'vars': rets}


def urlString(ctx=None, date=None, lang=None, tz=None):
   return calendarArgs(ctx, date, lang, tz)['urlstr']

def urlVars(ctx=None, date=None, lang=None, tz=None):
   return calendarArgs(ctx, date, lang, tz)['vars']


class Telescope(rend.Page):
   
   addSlash=True
   docFactory = loaders.xmlfile('booking.html', templateDir=template_path)
   buffered=True

   def __init__(self, avatarId=None):
      self.avatarId = avatarId
      log.debug("Requested Userlist by "+str(avatarId))
      rend.Page.__init__(self)

   def order_tlist(self, tlist):
      res = {}
      for i in tlist.keys():
         res[tlist[i]['name']] = tlist[i]
         res[tlist[i]['name']]['index'] = i
      return res

   def setPersistant(self, name, value):
      # We can get persistant variables here,
      # so, setting this in the parent shuld work
      if not 'telescope' in self.parent.childvars.keys():
         self.parent.childvars['telescope'] = {}
      self.parent.childvars['telescope'][name] = value


   def calHelper(self, date):
      try:
         args=self.pageargs
         lang=None
         if 'lang' in args.keys():
            lang = args['lang']
         tz=None
         if 'tz' in args.keys():
            tz = args['tz']
         y, m, d = str(date).split("-")
         if len(m) < 2: m="0"+m
         if len(d) < 2: d="0"+d
         date=y+m+d
         return urlString(False, date, lang, tz)
      except:
         return date

   def colorizeCalendar(self, ctx, myCal, month, tel):
      for k in month.keys():
         from twisted.internet import reactor
         pre = threads.blockingCallFromThread(reactor, dbutils.getBookingTime, month[k][0], month[k][1], tel)
         if len(pre) > 0:
            full = False
            # XXX Quando avremo anche le ore dovremo gestire anche il full!
            # XXX Gestire i messaggi per lingua!
            color="#66CCFF"
            text = "Parzialmente prenotato"
            if full:
               color="#FF6699"
               text="Completamente prenotato"
            myCal.viewEvent(str(k)[6:8], str(k)[6:8], color, text)
      return ctx.tag[loaders.htmlstr('<div>'+myCal.create()+'</div>')]


   def render_BookingCalendar(self, ctx, data):
      request = inevow.IRequest(ctx)
      self.pageargs=urlVars(ctx)
      myCal = calendar.MonthlyCalendar()
      date = self.pageargs['date']
      tz=self.pageargs['tz']
      y, m, d = splitDate(date)
      monthstart, monthstop, month = utils.getMonth(y, m, tz)
      if check_date(int(y), int(m), int(d)):
         myCal.year = int(y)
         myCal.month = int(m)
         myCal.setCurDay = int(d)
      myCal.link = request.path
      myCal.linkcallback = self.calHelper
      return threads.deferToThread(self.colorizeCalendar, ctx, myCal, month, self.actualtel)


   def threeDaysThread(self, date, tz):
      yesterday, tomorrow = getThreeDays(date, tz)
      return yesterday+"-"+str(date)+"-"+tomorrow

   def treeDaysCompose(self, result, ctx):
      return result

   def render_ThreeDays(self, ctx,  data):
      pageargs=urlVars(ctx)
      date = pageargs['date']
      tz = pageargs['tz']
      y, m, d = splitDate(date)
      #yesterday, tomorrow = getThreeDays(date)
      #return yesterday+"-"+str(date)+"-"+tomorrow
      return threads.deferToThread(self.threeDaysThread, date, tz).addCallback(
            self.treeDaysCompose, ctx
         )


   def helperSelection(self, var, check):
      if var == check:
         return 'selected="selected"'
      else:
         return ' '

   def render_BookingOptions(self, ctx, data):
      parg=urlVars(ctx)
      self.pageargs=parg
      request = inevow.IRequest(ctx)
      path = request.path
      lang=self.pageargs['lang']

      html="<div>"

      html+="<span>ANNO:</span>"
      html+='<select id="yopt" onChange="selChange(\''+path+'?'
      html+='tz='+parg['tz']+'&lang='+parg['lang']
      html+='&date=\', \'yopt\');">'
      m=parg['date'][4:6]
      d=parg['date'][6:8]
      for y in range(2000, 3000):
         html+="<option value=\""+str(y)+m+d+"\" "+ self.helperSelection(parg['date'], str(y)+m+d)
         html+=">"+str(y)+"</option>"
      html+="</select>"

      html+="<span>MESE:</span>"
      html+='<select id="mopt" onChange="selChange(\''+path+'?'
      html+='tz='+parg['tz']+'&lang='+parg['lang']
      html+='&date=\', \'mopt\');">'
      y=parg['date'][:4]
      d=parg['date'][6:8]
      for m in range(1, 13):
         html+="<option value=\""+y+str(m).zfill(2)+d+"\" "+ self.helperSelection(parg['date'], y+str(m).zfill(2)+d)
         html+=">"+str(m).zfill(2)+"</option>"
      html+="</select>"

      html+='<span>LINGUA:</span>'
      html+='<select id="langopt" onChange="selChange(\''+path+'?'
      html+="date="+parg['date']+"&tz="+parg['tz']+'&lang=\', \'langopt\');">'
      html+='   <option value="it" '+self.helperSelection(lang, 'it')
      html+='>it</option>'
      html+='   <option value="en" '+self.helperSelection(lang, 'en')
      html+='>en</option>'
      html+="</select>"
      
      html+="<span>FUSO:</span>"
      html+='<select id="tzopt" onChange="selChange(\''+path+'?'
      html+='date='+parg['date']+'&lang='+parg['lang']
      html+='&tz=\', \'tzopt\');">'
      for tz in timezones.worldtz:
         html+="<option value=\""+tz[0]+"\" "+ self.helperSelection(parg['tz'], tz[1])
         html+=">"+tz[1]+"</option>"
      html+="</select>"

      if self.avatarId:
         html+="<span>USERNAME:"+str(self.avatarId)+"</span>"

      html+="</div>"
      return ctx.tag[loaders.htmlstr(html)]
      

   def render_TelescopeList(self, ctx, data):
      self.tlist = self.order_tlist(self.command('GetTelescopes'))
      self.setPersistant('tlist', self.tlist)
      html = '<div id="menubar"><ul>'
      keys = self.tlist.keys()
      self.setPersistant('ikeys', keys)
      keys.sort()
      ikeys = []
      for i in keys:
         ikeys.append(self.tlist[i]['index'])
         html = html+'<li><a href="/booking/tel'+self.tlist[i]['index']+'?'+urlString(ctx)+'"'
         if str(i)[-1:] == str(self.actualtel):
            html= html+" style=\"background-color: #CCFF00;\""
         html=html+'>'+self.tlist[i]['name']+'</a></li>'
      html = html+"</ul></div>"
      log.debug(html)
      self.setPersistant('ikeys', ikeys)
      return ctx.tag[loaders.htmlstr(html)]
     

   def childFactory(self, ctx, data):
      return self.childPermissionDenied()


class Page(rend.Page):

   def renderHTTP(self, ctx):
      request = inevow.IRequest(ctx)
      request.setHeader('Location', '/booking/tel1?'+urlString())
      request.setResponseCode(302)
      return 'Refreshing...'


   def childFactory(self, ctx, data):
      if data[-1:] in self.command('GetTelescopes').keys():
         log.debug("Booking root data %s" % str(data))
         t=Telescope(self.parent.avatarId)
         t.actualtel=data[-1:]
         t.command = self.command
         t.childPermissionDenied = self.childPermissionDenied
         t.parent = self.parent
         t.render_HEAD = self.render_HEAD
         t.render_HEADER = self.render_HEADER
         t.render_FOOTER = self.render_FOOTER
         return t
      return self.childPermissionDenied()
