# ----------------------------------------------------------------------------
#       Copyright (C) 2013-2014 Huynh Vi Lam  <domovilam@gmail.com>
#
#       This file is part of pimucha.
#
#	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 3 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, see <http://www.gnu.org/licenses/>.
# ----------------------------------------------------------------------------

import datetime,logging,threading,time

logger = logging.getLogger()


def atdelay(attime):
    t = None
    d = datetime.date.strftime(datetime.datetime.today(),"%Y-%m-%d %H:%M:%S").split()
    at = attime.split()
    if len(at) == 1:
        t = d[0] + ' ' + at[0]
    elif at[0].lower() == 'now' and len(at) == 4:
        try:
            if at[3][0].lower() == 'h':
                t = datetime.date.strftime(datetime.datetime.today() + datetime.timedelta(hours=int(at[2])),'%Y-%m-%d %H:%M:%S')
            else:
                t = datetime.date.strftime(datetime.datetime.today() + datetime.timedelta(minutes=int(at[2])),'%Y-%m-%d %H:%M:%S')
        except Exception as e:
            logger.error("in parsing time delay %s : %s",repr(e.__class__), str(e))
            return "Error in parsing time delay"
    else:
        try:
            t = attime.strip()
            if datetime.datetime.strptime(t,'%Y-%m-%d %H:%M:%S') < datetime.datetime.today():
                logger.error("at time %s is in the past", repr(t))
                return "Error at time in the past"
        except Exception as e:
            logger.error("in parsing time delay %s : %s",repr(e.__class__), str(e))
            return "Error in parsing time delay"
    return t


def cv2cron(ptime):
    p = ptime.split()
    for i in range(len(p)):
        p[i] = p[i].split('=')
    return dict(p)


def actionsched(sched,type,actions,actionargs,attime,jobname=None):
    """
    actions = [ARM, DISARM, INPUT, SCRIPT, SENDTO]
    if action = INPUT
       args: Protocol HouseUnit(addressId) Function(on/off)
    admincmds = [CHECKD, RUN]
    """
    if not jobname: jobname = actionargs.replace(' ','_')
    p = actionargs.split()
    action = p[0]
    if (action not in actions) or (len(p) < 2): return 'Error parsing parameters..'
    args = ' '.join(p[1:])
    if type == '-every-':
        iv = attime.strip()
        if not iv.isdigit(): return 'Syntax error for time interval %s (integer in minutes only)' % repr(attime)
        p[1] = iv
    return schedule(sched,type,jobname,args,attime,actions[action])


def parsched(lparam):
    """
    lparam : (action/cmd) args (type) attime
    type in [-at-, -every-, -cron-]
    if type = -at-
        attime : '2013-09-06 16:30:05'
        attime : '16:30:05'
        attime : 'now + 2 min/hour'
    if type = -cron-
        'year month day week day_of_week hour minute'
        'minute=5' : at 5 minutes of every hour ...
    """
    if isinstance(lparam,list):
        p = ' '.join(lparam)
    else:
        p = lparam
    for type in ['-at-', '-every-', '-cron-']:
        try:
            actioncmd,attime = p.split(type)
            return type,actioncmd,attime
        except:
            pass
    return None


def schedule(sched,type,jobname,pcmd,ptime,schedfct):
    """
    [sched,'-at-',jobname,'pl a1 on','2013-09-06 16:30:05',INPUTq.put_nowait]
    [sched,'-at-',jobname,'pl a1 on','16:30:05',INPUTq.put_nowait]
    [sched,'-at-',jobname,'pl a1 on','now + 2 min/hour',INPUTq.put_nowait]
    """
    try:
        if type == '-at-':
            t = atdelay(ptime)
            if not t: return ("Error parsing time parameter %s..." % ptime)
            sched.add_date_job(lambda: schedfct(pcmd), t, name=jobname)
        elif type == '-every-':
            t = int(ptime)
            sched.add_interval_job(lambda: schedfct(pcmd),minutes=t,name=jobname)
        elif type == '-cron-':
            args = [lambda: schedfct(pcmd)]
            kargs = cv2cron(ptime)
            kargs.update({'name':jobname})
            sched.add_cron_job(*args,**kargs)
    except Exception as e:
        logger.error("%s : %s",repr(e.__class__), str(e))
        return ("Error ading job to scheduler")
    logger.debug("Adding jobname : %s executing at %s...",jobname,repr(ptime))
    return ("Adding jobname : %s executing at %s..." % (jobname,repr(ptime)))


def schedlistjobs(sched):
    jobs = sched.get_jobs()
    res = []
    for job in jobs:
        res.append(repr(job))
    if len(res) == 0: return 'Nothing in jobs queue'
    return '\n'.join(res)


def schedunsched(sched,name):
    jobs = sched.get_jobs()
    for job in jobs:
        if name in (repr(job)):
            sched.unschedule_job(job)
            logger.debug("Job %s is succesfully unscheduled", name)
            return ("Job %s is succesfully unscheduled" % name)
    else:
        logger.error("Job name %s is not in the jobs list", name)
        return ("Job name %s is not in the jobs list" % name)
