using System;
using System.Linq;
using System.ComponentModel;
using GCHR.Model;
using GCHR.View;

namespace GCHR.Control.Tasks
{
    abstract class Task
    {
        protected ThreadXData Data = ThreadXData.GetInstance();
        protected Konfiguration Config = Konfiguration.GetInstance();
        
        public int ID;
        private readonly string _name;
        public Ampel Ampel;
        public BackgroundWorker Worker;
        private int[] _warteliste;
        
        public static Task CreateInstance(int id, string name, RunWorkerCompletedEventHandler completed, int[] waitfor)
        {
            var currentTask = GetTask(id, name);
            currentTask.Worker.RunWorkerCompleted += completed;
            currentTask.SetWarteliste(waitfor);
            return currentTask;
        }

        private static Task GetTask(int id, string name)
        {
            switch (name)
            {
                case "Kontenrahmen":
                    return new KontenrahmenAlt(id, name);
                case "UebersetzungSuSa":
                    return new UebersetzungSuSa(id, name);
                case "UebersetzungStat":
                    return new UebersetzungStat(id, name);
                case "ManuelleKonten":
                    return new ManuelleKonten(id, name);
                case "DatenimportSuSa":
                    return Datenimport.DatenimportSuSa(id, name);
                case "DatenimportStat":
                    return Datenimport.DatenimportStat(id, name);
                case "Verarbeitung":
                    return new Verarbeitung(id, name);
                case "Verrechnung":
                    return new Verrechnung(id, name);
                case "Export":
                    return new Export(id, name);
                default:
                    return new DummyTask(id, name);
            }
        }

        protected Task(int id, string name)
        {
            ID = id;
            _name = name;
            Ampel = new Ampel();

            Worker = new BackgroundWorker
                         {
                             WorkerReportsProgress = true,
                             WorkerSupportsCancellation = false
                         };
            Worker.DoWork += DoWork;
        }

        private void DoWork(object sender, DoWorkEventArgs e)
        {
            ReportProgress(5);
            AufgabeAusfuehren();
            ReportProgress(100);
        }

        protected abstract void AufgabeAusfuehren();

        public void SetWarteliste(int[] waitfor)
        {
            _warteliste = waitfor;
        }

        public void WartelisteAktualisieren(int aufgabeId)
        {
            if (_warteliste == null) return;
            for (var i = 0; i < _warteliste.Count(); i++)
            {
                if (_warteliste[i] == aufgabeId)
                {
                    _warteliste[i] = -1;
                }
            }
        }

        public override String ToString()
        {
            return _name;
        }

        public bool TryRun()
        {
            if (_warteliste == null)
                return false;

            for (var i = 0; i < _warteliste.Count(); i++)
            {
                if (_warteliste[i] != -1)
                    return false;
            }

            _warteliste = null;
            Worker.RunWorkerAsync();
            return true;
        }

        public void RegisterAmpel(Ampel ampel)
        {
            Ampel = ampel;
            Worker.ProgressChanged += (s1, e1) => Ampel.ProgressChanged(e1.ProgressPercentage, e1.UserState);
            Ampel.Reset();
        }

        public void ReportProgress(int percentProgress)
        {
            Worker.ReportProgress(percentProgress);
        }

        public void ReportProgress(int percentProgress, object userState)
        {
            Worker.ReportProgress(percentProgress, userState);
        }
    }

    class DummyTask : Task
    {
        public DummyTask(int id, string name) 
            : base(id, name) { }
        
        protected override void AufgabeAusfuehren()
        {

        }
    }
}