//  
//  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[] ListOfTasks = (Task[])Tasks.ToArray(typeof(Task));
                for (int i = 0; i < ListOfTasks.Length; i++)
				{
					Task CurrentTask = ListOfTasks[i];

                    //Verify current time with settime , with extra check if it is a scheduledaction or delayedcommand
                    //CurrentTime is equal or higher than settime. Execute task
                    if (CurrentTask.IsToExecuteNow(CurrentTask.ScheduledAction))
                    {
                        if (CurrentTask.executed == false)
                        {
                            //Debug messages in console.
                            if (newCfg.varsLapper.DisplayLoops == 1)
                            {
                                Console.ForegroundColor = ConsoleColor.Yellow;
                                Console.WriteLine(System.DateTime.Now + ": HostLoop Sub:" + CurrentTask.Command + " (" + CurrentTask.ScheduledAction + ") Executed");
                                Console.ForegroundColor = ConsoleColor.White;
                            }

                            CurrentTask.executed = true;
                            newCfg.executeFunction(CurrentTask.Command, null, null);
                            if (CurrentTask.IsOnceToExecuteOnly)
                                CurrentTask.toRemove = true;
                        }
                    }
                    //CurrentTime is NOT equal or higher than settime. Do not execute task
                    else
                    {
                        CurrentTask.executed = false;
                        //Debug messages in console.
                        if (newCfg.varsLapper.DisplayLoops == 1)
                        {
                            Console.ForegroundColor = ConsoleColor.Red;
                            Console.WriteLine(System.DateTime.Now + ": HostLoop Sub:" + CurrentTask.Command + " (" + CurrentTask.ScheduledAction + ")  Canceled");
                            Console.ForegroundColor = ConsoleColor.White;
                        }
                    }
                }
				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 ScheduledAction = false;
        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;
            this.ScheduledAction = false;

            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
            {
                this.ScheduledAction = true;
                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;
                    }

                }
            }
        }

        bool Equals(DateTime date, bool scheduled)
        {
            //Console.WriteLine("DEBUG: (" + hr + ":" + min + ":" + s + ") <> (" + date.Hour + ":" + date.Minute + ":" + date.Second + ")");
            bool ExecuteTask = false;

            //RegisterScheduled Actions
            if (scheduled == true)
            {
                if ((date.Year == yr || yr == -1) && (date.Month == mon || mon == -1) && (date.Day == day || day == -1) && ((int)date.DayOfWeek == dayOfWeek || dayOfWeek == -1) &&
                    (hr == -1 || date.Hour == hr) && (date.Minute == min || min == -1) && (date.Second == s || s == -1))
                {
                    ExecuteTask = true;
                }
            }

            //(Priv/Host) DelayedCommand Loops
            if (scheduled == false)
            {
                //year year
                if ((date.Year == yr) && (date.Month == mon) && (date.Day == day))
                {
                    if ((date.Hour >= hr) || (hr == 23 && date.Hour == 00))
                    {
                        //Compare Hours & check time difference
                        if (date.Minute >= min)
                        {
                            //Compare Seconds & check time difference
                            if ((date.Second == s) || (date.Second > s) || (s == 59 && date.Second > 00))
                            {
                                ExecuteTask = true;
                            }
                        }
                    }
                }
            }
            return ExecuteTask;
        }

        public bool IsToExecuteNow(bool IsScheduled)
        {
            //Returns true/false (bool)
            return this.Equals(System.DateTime.Now, IsScheduled);
        }
    }
}
