//  
//  Task.cs
//  
//  Author:
//       Robert BRACCAGNI alias Gai-Luron <lfsgailuron@free.fr>
// 
//  Copyright (c) 2010 Gai-Luron
// 
//  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/>.



using System;
using System.IO;
using System.Text;
using System.Net;


namespace LFSLapper
{
    partial class LFSClient
    {
        void loopTask()
        {
            try
            {
                Task[] listTask = (Task[])Tasks.ToArray(typeof(Task));
                for (int i = 0; i < listTask.Length; i++)
                {
                    Task currTask = listTask[i];

                    if (currTask.IsToExecuteNow(currTask.executed,currTask.IsOnceToExecuteOnly))
                    {
                        //Debug option
                        if (newCfg.varsLapper.DisplayLoops == 1)
                        {
                            Console.ForegroundColor = ConsoleColor.Yellow;
                            Console.WriteLine(System.DateTime.Now + ": HostLoop ID:" + currTask.Command);
                        }

                        if (currTask.executed == false)
                        {
                            currTask.executed = true;
                            newCfg.executeFunction(currTask.Command, null, null);
                            if (currTask.IsOnceToExecuteOnly)
                                currTask.toRemove = true;
                        }
                    }
                    else
                    {
                        currTask.executed = false;
                        //Debug option
                        if (newCfg.varsLapper.DisplayLoops == 1)
                        {
                            Console.ForegroundColor = ConsoleColor.Red;
                            Console.WriteLine(System.DateTime.Now + ": HostLoop ID:" + currTask.Command + " Canceled");
                        }
                    }
                }
                for (int i = Tasks.Count - 1; i >= 0; i--)
                {
                    if ((Tasks[i] as Task).toRemove)
                        Tasks.RemoveAt(i);
                }
            }
            catch (Exception ex)
            {

                myDebug.WriteLine("err", "Error on Task " + ex.ToString());
            }
        }
    }
    public class Task
    {
        public readonly string idTask;
        public readonly string Command;
        public readonly string Cron;
        public readonly bool IsOnceToExecuteOnly = true;
        public bool executed = false;
        public bool toRemove = false;

        int s = -1;
        int min = -1;
        int hr = -1;
        int day = -1;
        int dayOfWeek = -1;
        int mon = -1;
        int yr = -1;

        public class GLScriptException : Exception
        {
            public GLScriptException(string message) : base(message) { }
            public GLScriptException(string message, Exception innerException) : base(message, innerException) { }
        }


        public Task(string idTask, string Command, DateTime DateTime)
        {
            this.idTask = idTask;
            this.Command = Command;

            s = DateTime.Second;
            min = DateTime.Minute;
            hr = DateTime.Hour;
            day = DateTime.Day;
            mon = DateTime.Month;
            yr = DateTime.Year;

            IsOnceToExecuteOnly = true;
        }

        public Task(string idTask, string Command, string CronSchedule)
        {
            this.idTask = idTask;
            this.Command = Command;
            this.Cron = CronSchedule;

            //parse CronSchedule
            System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"\d+|\*");
            System.Text.RegularExpressions.MatchCollection mc = regex.Matches(CronSchedule);

            if (!regex.IsMatch(CronSchedule) || mc.Count != 7)
            {
                throw new GLScript.GLApp.GLScriptException("Error in RegisterScheduleAction: incorrect number of fields  ( * * * * * * * ) " + mc.Count + " / 7");
            }
            else
            {
                int val = 0;
                for (int i = 0; i < mc.Count; i++)
                {
                    if (mc[i].Value == "*")
                    {
                        val = -1;
                        IsOnceToExecuteOnly = false;
                    }
                    else
                        val = int.Parse(mc[i].Value);

                    switch (i)
                    {
                        case 0: this.s = val; break;
                        case 1: this.min = val; break;
                        case 2: this.hr = val; break;
                        case 3: this.dayOfWeek = val; break;
                        case 4: this.day = val; break;
                        case 5: this.mon = val; break;
                        case 6: this.yr = val; break;
                            //default: break;
                    }

                }
            }
        }

        public bool IsToExecuteNow(bool executed,bool onlyonceexecuted)
        {
            DateTime CurrentDateTime = DateTime.Now;
            bool ExecuteTask = false;
           
            ExecuteTask =
            //Year
            ((((CurrentDateTime.Year == yr || yr == -1) &&
            //Month
            (CurrentDateTime.Month == mon || mon == -1) &&
            //Day
            (CurrentDateTime.Day == day || day == -1) &&
            //DayOfweek
            ((int)CurrentDateTime.DayOfWeek == dayOfWeek || dayOfWeek == -1)) &&
            //Hours
            (CurrentDateTime.Hour == hr || hr == -1) &&
            //Minutes
            (CurrentDateTime.Minute == min || min == -1) &&
            //Seconds
            (CurrentDateTime.Second == s || s == -1)) && (onlyonceexecuted == false)) || (executed == false && onlyonceexecuted == true && (CurrentDateTime.Hour >= hr && CurrentDateTime.Minute >= min && CurrentDateTime.Second >= s)) ;

            return ExecuteTask;
        }
    }
}
