#!/usr/bin/env python3
# GPL. (C) 2007-2012 Paolo Patruno.

# This program 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 2 of the License, or 
# (at your option) any later version. 
# 
# This program 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 this program; if not, write to the Free Software 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
# 

# ToDo:
# controllare altri conflitti in districa oltre ai jingles
# utilizzare mp3splt per spezzare i programmi per fare gli inserimenti pubblicitari
# alternare meglio i jingle tenendo in considerazione la priorita

import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'autoradio.settings'
from django.conf import settings

import autoradio.settings
import autoradio.autoradio_config
from autoradio import daemon
from autoradio import _version_

autoradiod = daemon.Daemon(
        stdin="/dev/null",
        stdout=autoradio.autoradio_config.logfile,
        stderr=autoradio.autoradio_config.errfile,
        pidfile=autoradio.autoradio_config.lockfile,
        user=autoradio.autoradio_config.user,
        group=autoradio.autoradio_config.group,
        env=autoradio.autoradio_config.env
)


def main():

    import logging,os,sys,errno,signal,logging.handlers
    import subprocess
    try:
        import thread
    except:
        import _thread as thread
    import datetime
    import time as timesleep
    #from threading import *

    import django
    django.setup()

    import autoradio.autoradio_core

    formatter=logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s",datefmt="%Y-%m-%d %H:%M:%S")
    handler = logging.handlers.RotatingFileHandler(autoradio.autoradio_config.logfile, maxBytes=5000000, backupCount=10)
    handler.setFormatter(formatter)
    
    # Add the log message handler to the root logger
    logging.getLogger().addHandler(handler)
    logging.getLogger().setLevel(logging.INFO)


    logging.info('Starting up autoradiod version '+_version_)


    if (autoradio.autoradio_config.player == "amarok1") :
        import autoradio.manageamarok as manageplayer 

    elif (autoradio.autoradio_config.player == "xmms"):
        #    from managepytone import *
        import autoradio.managexmms as manageplayer
        import autoradio.xmmsweb as playerweb

    elif (autoradio.autoradio_config.player == "audacious" 
          or autoradio.autoradio_config.player == "amarok" 
          or autoradio.autoradio_config.player == "vlc"
          or autoradio.autoradio_config.player == "AutoPlayer"):

#        import autoradio.manageaudacious as manageplayer
#        import autoradio.audaciousweb as playerweb
        import autoradio.managempris as manageplayer
        import autoradio.mprisweb as playerweb

    else:
        logging.error('wrong player %s' % autoradio.autoradio_config.player)
        raise Exception()

    #def signalhandler(signum, frame):
    #    logging.info( 'Signal handler called with signal %d', signum)

    #signal.signal(signal.SIGALRM, signalhandler)

    f = open(autoradio.autoradio_config.timestampfile, "w")
    f.write(str(datetime.datetime.now()))
    f.close()

    #we want to run a single process

    try:

      # now we can start to do our work
      # time constant

      # this is the first and last time that I set now with the current time
      now=datetime.datetime.now()

      first = True

      if (autoradio.autoradio_config.player == "amarok1") :
          kapp=KdeInit()
          function=manageplayer.ManageAmarok
          ok=amarok_watchdog(kapp)

      else:
  #        function=ManagePytone
          session=0

          # parte un thread pe monitorare via web il player
          #t = Timer(5.0, xmmsweb.start_http_server)
          #t.start()

          #os.system("python xmmsweb.py&")
          #p = subprocess.Popen("xmmsweb.py")


          if (autoradio.autoradio_config.player == "amarok1"):
              ok=manageplayer.amarok_watchdog(kapp)
          elif (autoradio.autoradio_config.player == "xmms"):
              t = thread.start_new_thread(playerweb.start_http_server,())
              ok=manageplayeer.xmms_watchdog(session)
          elif (autoradio.autoradio_config.player == "audacious" 
                or autoradio.autoradio_config.player == "amarok" 
                or autoradio.autoradio_config.player == "vlc"):
              t = thread.start_new_thread(playerweb.start_http_server,())
              ok=manageplayer.player_watchdog(autoradio.autoradio_config.player,session)
          elif (autoradio.autoradio_config.player == "AutoPlayer"):
              ok=manageplayer.player_watchdog(autoradio.autoradio_config.player,session)

      while ( True):

          scheds=autoradio.autoradio_core.schedules([])
          scheds.get_all_refine(now)
          for schedule in scheds:

              scheduledatetime=schedule.scheduledatetime
              filename=schedule.filename
              type=schedule.type
              emission_done=schedule.emission_done

              if ( emission_done != None ):
                  if ( type == "program" ):
                      #la trasmissione ha una schedula con un'unica emissione prevista
                      logging.debug( " %s %s %s schedula already done; ignore it !",type,scheduledatetime,emission_done)
                      continue

                  if ( type == "spot" ):
                      # considero una emissione effettuata se e' avvenuta nell'intorno delle 3 ore
                      if ( abs(emission_done - scheduledatetime) < datetime.timedelta(minutes=180)): 
                          logging.debug(" %s %s %s schedula already done; ignore it !", type,scheduledatetime,emission_done)
                          continue

                  if ( type == "playlist" ):
                      # I assume the emission is done if it happen around 3 hours
                      if ( abs(emission_done - scheduledatetime) < datetime.timedelta(minutes=180)): 
                          logging.debug (" %s %s %s schedula already done; ignore it !",type,scheduledatetime,emission_done)
                          continue


              delta=( scheduledatetime - now)
              sec=manageplayer.secondi(delta)
              #schedule for the nest minsched minutes starting from minsched minuti forward
              #if it is the first time I start from minsched minuti in the past
              if (first and ( type == "program" or type == "spot" or type == "playlist")): 
                  #recovery programmi, playlist e pubblicita' not emitted in a ragionable past time range
                  startschedsec=-60 * autoradio.autoradio_config.minsched
              elif (first and ( type == "jingle")):
                  startschedsec=0
              else:
                  startschedsec=60*autoradio.autoradio_config.minsched


              endschedsec = 60*autoradio.autoradio_config.minsched*2
              if ( startschedsec < sec and sec <= endschedsec ):

                  #print "ora schedulata", scheduledatetime
                  #print "ora attuale", datetime.now()

                  if (autoradio.autoradio_config.player == "amarok1") :
                      threadschedule=manageplayer.ScheduleProgram(kapp,function,operation,filename,scheduledatetime,obj)
                  else:
                      #threadschedule=ScheduleProgram(session,function,operation,filename,scheduledatetime,obj,shuffle,length)
                      threadschedule=manageplayer.ScheduleProgram(autoradio.autoradio_config.player,session,schedule)

                  logging.debug (" %s %s programmed for %s seconds forward", type,filename,threadschedule.deltasec)
                  threadschedule.start()

          first = False
          sleepsec=autoradio.autoradio_config.minsched/5.*60.

          #now I advance minsched and wait the right time to proced
          now=now+datetime.timedelta(0,60*autoradio.autoradio_config.minsched)
          while ( datetime.datetime.now() < now):
              if (autoradio.autoradio_config.player == "amarok1"):
                  ok=manageplayer.save_status(kapp)

              else:
                  ok=manageplayer.save_status(session)

              if ( ok ) :

                  f = open(autoradio.autoradio_config.timestampfile, "w")
                  f.write(str(datetime.datetime.now()))
                  f.close()

              logging.debug ( "sleeping for %s seconds:%s  %d",sleepsec,__name__,os.getpid())

              #signal.alarm(0)
              timesleep.sleep(sleepsec)

              #os.system("sleep 60")
              #target = time.time()
              #while True:
              #   now = time.time()
              #   if now >= target+60: break
              #   os.sleep(target-now)

              #logging.debug ( "wake up: %s  %d",__name__,os.getpid() )

          #sometime adjust playlist (will be deleted)
          if (autoradio.autoradio_config.player == "amarok1"):
              ok=manageplayer.amarok_watchdog(kapp)
          elif (autoradio.autoradio_config.player == "xmms"):
              ok=manageplayer.xmms_watchdog(session)
          elif (autoradio.autoradio_config.player == "audacious" 
                or autoradio.autoradio_config.player == "amarok" 
                or autoradio.autoradio_config.player == "vlc"
                or autoradio.autoradio_config.player == "AutoPlayer"):

              ok=manageplayer.player_watchdog(autoradio.autoradio_config.player,session)


    except KeyboardInterrupt :

      logging.info('All threads terminated for keyboard interrupt' )
      return 1

    except SystemExit:

      logging.info('Stopped OK')
      return 0

    except:
      import traceback
      msg = traceback.format_exc()
      logging.error(msg)
      logging.info('Stopping')

      return 2

    else:
      msg = "error without traceback; what happens ?!?!"
      logging.error(msg)
      logging.info('Stopping')

      return 3

    
if __name__ == '__main__':

    import sys, os

    # this is a triky for ubuntu and debian that remove /var/run every boot
    # ATTENTION, this should be a security problem
    path=os.path.dirname(autoradio.autoradio_config.lockfile)
    if (not os.path.lexists(path) and path == "/var/run/autoradio" ):
        os.mkdir(path)
        if (os.getuid() == 0):

            user=autoradio.autoradio_config.user
            group=autoradio.autoradio_config.group
            if user is not None and group is not None:
                from pwd import getpwnam
                from grp import getgrnam
                uid = getpwnam(user)[2]
                gid = getgrnam(group)[2]
                os.chown(path,uid,gid)

    if autoradiod.service():

        sys.stdout.write("Autoradiod version "+_version_+"\n")
        sys.stdout.write("Daemon started with pid %d\n" % os.getpid())
        sys.stdout.write("Daemon stdout output\n")
        sys.stderr.write("Daemon stderr output\n")

        sys.exit(main())  # (this code was run as script)
