#coding: utf-8
# +-------------------------------------------------------------------
# | 宝塔Windows面板
# +-------------------------------------------------------------------
# | Copyright (c) 2015-2016 宝塔软件(http://www.bt.cn) All rights reserved.
# +-------------------------------------------------------------------
# | Author: 沐落 <cjx@bt.cn>
# +-------------------------------------------------------------------

import public,db,os,time,re,json
import threading
class panelCrontab:

    _reload = False;
    _ctime = {}
    def __init__(self):
        pass

    #处理新版计划任务，临时处理
    def get_crontab_time(self,stime):

        if type(stime) == str:
            return stime

        if type(stime) == bytes:
            stime = stime.decode()

        stime = json.loads(stime)
        if type(stime) == list:
            if  len(stime) > 0:
                return stime[0]
            return ""
        return stime

    #处理任务
    def process_fun(self,item):
        self._ctime = self.get_ctime()
        try:
            #print( self._ctime)
            if item['status'] == 1:
                runtime = 0
                try:
                    runtime = int(item['nexttime'])
                except :pass
                #print(public.format_date(times=runtime))
                stype = item['type']
                if not runtime:

                    where1 = self.get_crontab_time(item['where1'])
                    where_hour = self.get_crontab_time(item['where_hour'])
                    where_minute = self.get_crontab_time(item['where_minute'])

                    loacl_time = self._ctime['local_time']
                    if stype == 'day':
                        runtime = self.get_local_time('%s-%s-%s %s:%s:00' % (loacl_time.tm_year,loacl_time.tm_mon,loacl_time.tm_mday,where_hour,where_minute))

                    elif stype=='day-n':
                        runtime =  self.get_local_time('%s-%s-%s %s:%s:00' % (loacl_time.tm_year,loacl_time.tm_mon,loacl_time.tm_mday,where_hour,where_minute))
                    elif stype == 'hour':
                        runtime = self.get_local_time('%s-%s-%s %s:%s:00' % (loacl_time.tm_year,loacl_time.tm_mon,loacl_time.tm_mday,loacl_time.tm_hour,where_minute))
                    elif stype == 'hour-n':
                        runtime =  self.get_local_time('%s-%s-%s %s:%s:00' % (loacl_time.tm_year,loacl_time.tm_mon,loacl_time.tm_mday,loacl_time.tm_hour,where_minute))
                    elif stype == 'minute-n':
                        runtime = int(time.time())
                    elif stype == 'week':
                        #处理周任务
                        total_day = 0
                        week = int(where1)
                        if week >= int(self._ctime['week']):
                            total_day = week - int(self._ctime['week'])
                        else:
                            total_day = week + 7 - int(self._ctime['week'])
                        ttime = self.calc_time(int(time.time()),total_day,'day')
                        loacl_time = time.localtime(ttime)
                        next_time = self.get_local_time('%s-%s-%s %s:%s:00' % (loacl_time.tm_year,loacl_time.tm_mon,loacl_time.tm_mday,where_hour,where_minute))
                        runtime = self.calc_time(next_time,-1,stype)
                    elif stype == 'month':
                        runtime = self.get_local_time('%s-%s-%s %s:%s:00' % (loacl_time.tm_year,loacl_time.tm_mon,where1,where_hour,where_minute))

                print("计划任务",item['name'],public.format_date(times=runtime))
                if int(self._ctime['long_time']) >= int(runtime):
                    print("执行计划任务",item)
                    t = threading.Thread(target=self.run_threading,args=(item,runtime))
                    t.setDaemon(True)
                    t.start()
        except :
            public.writeFile('logs/crontab.log',public.get_error_info())
        return True

    #执行线程
    def run_threading(self,sdata,runtime):

        #获取下次运行时间
        next_time = self.get_next_time(runtime,sdata)
        print("下次执行时间",next_time)
        ctime = int(self._ctime['long_time'])
        while next_time <= ctime:
            next_time = self.get_next_time(next_time,sdata)

        public.M('crontab').where('id=?',(sdata['id'],)).save("pretime,nexttime",(ctime,int(next_time)))
        path =  public.GetConfigValue('setup_path') + '/cron/' + sdata['echo']

        if os.path.exists(path):
            pid_path = "{}.pid".format(path)
            try:
                if os.path.exists(pid_path):
                    public.writeFile("{}.skip".format(path),'{} ------ skip \n'.format(public.format_date("%Y-%m-%d %H:%M:%S",ctime)),'a+')
                    return

                public.writeFile(pid_path,'True')

                shell = public.readFile(path)
                public.ExecShell(shell+' >> ' + path + '.log' + ' 2>&1')
                if os.path.exists(pid_path): os.remove(pid_path)
            except:
                if os.path.exists(pid_path): os.remove(pid_path)
                public.writeFile('logs/crontab.log',public.get_error_info())

    #获取下次更新时间
    def get_next_time(self,runtime,item):
        next_time = 0
        runtime = int(runtime)
        loacl_time = self._ctime['local_time']
        stype = item['type']


        where1 = self.get_crontab_time(item['where1'])
        where_hour = self.get_crontab_time(item['where_hour'])
        where_minute = self.get_crontab_time(item['where_minute'])

        if stype == 'day':
            next_time = self.calc_time(runtime,1,stype)
        elif stype=='day-n':
            next_time = self.calc_time(runtime,int(where1),'day')
            next_time = self.calc_time(next_time,int(where_hour),'hour')
            next_time = self.calc_time(next_time,int(where_minute),'minute')
        elif stype == 'hour':
            next_time = self.calc_time(runtime,1,stype)
        elif stype == 'hour-n':
            try:
                next_time = self.calc_time(runtime,int(where_hour),'hour')
            except :
                next_time = self.calc_time(runtime,int(where1),'hour')
            next_time = self.calc_time(next_time,int(where_minute),'minute')
        elif stype == 'minute-n':
            try:
                print(where_minute,"where_minute")
                next_time = self.calc_time(runtime,int(where_minute),'minute')
            except :
                next_time = self.calc_time(runtime,int(where1),'minute')
        elif stype == 'week':
            next_time = self.calc_time(runtime,1,stype)
        elif stype == 'month':
            next_time = self.calc_time(runtime,1,stype)
        return next_time

    #计算时间
    def calc_time(self,ctime,cycle = 1,unit = 'day'):
        rtime = 0
        if unit == 'day':
            rtime = ctime + cycle * 86400
        elif unit == 'hour':
            rtime = ctime + cycle * 3600
        elif unit == 'minute':
            rtime = ctime + cycle * 60
        elif unit == 'month':
            import datetime
            try:
                from dateutil.relativedelta import relativedelta
            except :
                os.system(public.get_run_pip('[PIP] install python-dateutil'))
                from dateutil.relativedelta import relativedelta
            dt =  datetime.datetime.fromtimestamp(ctime)
            ndt = dt + relativedelta(months=+1)
            rtime = time.mktime(ndt.timetuple())
        elif unit == 'week':
            rtime = ctime + cycle * 7 * 86400
        return rtime


    #获取更新时间
    def get_ctime(self):
        data = {}
        data['long_time'] = int(time.time())
        data['local_time'] = time.localtime()
        data['week'] =  time.strftime('%w', data['local_time'])
        return data

    #格式化时间
    def get_local_time(self,now_time):

        time_array = time.strptime(now_time, "%Y-%m-%d %H:%M:%S")
        timestamp = time.mktime(time_array)
        return timestamp
