using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace Art_of_War
{
    class Spiel
    {
        #region Variablendeklarierung
        System.Threading.Timer timer;
        AktuelleSpielfeldwerte aktuelleSpielfeldwerte;
        LevelEinstellungen aktuellelevelsettings;
        Input input;


        private gewaehlteBasen[] Playerinput= new gewaehlteBasen[2];

        

        struct gewaehlteBasen
        {
            public Basis ersteBasis;
            public Basis zweiteBasis;
        }

        //Alternative: gewaehlteBasen als Klasse statt struct
        //private class gewaehlteBasen
        //{
        //    public Basis ersteBasis;
        //    public Basis zweiteBasis;

        //    public gewaehlteBasen()
        //    {
        //        this.ersteBasis = null;
        //        this.zweiteBasis = null;
        //    }
        //};
        //gewaehlteBasen[] Playerinput = new gewaehlteBasen[2];    

        #endregion
        #region Events
        public event EventHandler<GrafikEventArgs> grafikdatenunterwegslisteupdate;

        #endregion


        #region Konstruktor
        public Spiel(PermanenteEinstellungen permanentsettings, LevelEinstellungen levelsettings, Input input)
        {
            //Debug.WriteLine("Instanz vom spiel erzeugt!");
            timer = new System.Threading.Timer(o=>zyklusdurchlaufen(),null,3000, 100);
            aktuelleSpielfeldwerte = new AktuelleSpielfeldwerte();

            //Die folgenden zwei Zeilen sind nur, wenn Playerinput Klasse ist und kein struct
            //Playerinput[0] = new gewaehlteBasen();
            //Playerinput[1] = new gewaehlteBasen();

            this.aktuellelevelsettings = levelsettings;
            this.input = input;
            this.input.KeyPressed += new System.Windows.Forms.KeyEventHandler(input_KeyPressed);

        }
        #endregion

        #region Methoden
        void input_KeyPressed(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            Debug.WriteLine("Bin im Keypressed-Event drin!");
            for (int i=0; i< aktuellelevelsettings.basisliste.Count; i++)
            {
                var element=aktuellelevelsettings.basisliste;
                

                //Keyboardeingabe über die Ziffern bei Spieler 1
                if (e.KeyValue-48 == element[i].ID)
                {
                    if (Playerinput[0].ersteBasis == null && element[i].spielerzugehoerigkeit == zugehoerigkeit.rot)
                        Playerinput[0].ersteBasis= element[i];
                    if (Playerinput[0].ersteBasis!= null && Playerinput[0].zweiteBasis==null && Playerinput[0].ersteBasis.ID!=element[i].ID)
                        Playerinput[0].zweiteBasis=element[i];
                }
                //Keyboardeingabe über den Ziffernblock bei Spieler 2
                if (e.KeyValue - 96 == element[i].ID)
                {
                    if (Playerinput[1].ersteBasis == null && element[i].spielerzugehoerigkeit == zugehoerigkeit.blau)
                        Playerinput[1].ersteBasis = element[i];
                    if (Playerinput[1].ersteBasis != null && Playerinput[1].zweiteBasis == null && Playerinput[1].ersteBasis.ID != element[i].ID)
                        Playerinput[1].zweiteBasis = element[i];
                }


            }
            Debug.WriteLine("Keyvalue der gedrückten Taste: " + e.KeyValue);
            Debug.WriteLine("Wert (nach Tastendruck) von ClickedErsteBasis: " + Playerinput[0].ersteBasis + " und ClickedzweiteBasis: " + Playerinput[0].zweiteBasis);
        }



        //Fragt Spielparameter ab und ändert sie ggf. nach jedem Zyklus
        void zyklusdurchlaufen()
        {
            Debug.WriteLine("Zugehoerigkeit von Basis 2: " + aktuellelevelsettings.basisliste[2].spielerzugehoerigkeit);

            //Debug.WriteLine("Bin in Zyklusdurchlaufen drin");
            //Debug.WriteLine("Wert von clickedErsteBasis: " + clickedErsteBasis);
            //Debug.WriteLine("Wert von clickedZweiteBasis: " + clickedZweiteBasis);

        //Alle Basen der Spieler durchgehen und wenn nicht Neutral, 1 Einheit draufaddieren.
            foreach (var element in aktuellelevelsettings.basisliste)
            {
                if (element.spielerzugehoerigkeit != zugehoerigkeit.neutral)
                    if (element.einheiten < (((float)element.Basengroesse)*20))
                    element.einheiten += ((float)element.Basengroesse)/10;
                Debug.WriteLine(element.einheiten.ToString());
            }

            if (aktuelleSpielfeldwerte.Unterwegsliste != null)
            {

                foreach (var element in aktuelleSpielfeldwerte.Unterwegsliste)
                {
                    element.positionx += element.speedx;
                    element.positiony += element.speedy;
                }
            }

            //Debug.WriteLine("Spieler1basenzahl=" + spieler1basenzahl);
            Debug.WriteLine("aktuelle Einheiten in Basis 0 :" + aktuellelevelsettings.basisliste[0].einheiten);


            //Alle Einheiten unterwegs durchgehen und wenn Dauer 0, bei Ziel einheitenzahl und evtl. Zugehörigkeit ändern
            for (int i = 0; i < aktuelleSpielfeldwerte.Unterwegsliste.Count; i++)
            {
                var element = aktuelleSpielfeldwerte.Unterwegsliste[i];

                element.dauer--;
                //Zeit ist abgelaufen, Einheit ist  bei Basis angekommen
                if (element.dauer <= 0)
                {
                    //Wenn andere Basis dem Spieler schon gehört
                    if (element.spielerzugehoerigkeit == element.Ziel.spielerzugehoerigkeit)
                    {
                        //Einheiten bei Ziel aufaddieren
                        element.Ziel.einheiten += element.anzahl;
                    }

                    //Sonst (Basis gehört Gegner oder ist neutral)
                    else
                    {
                        //Wenn Gegner zuwenig Einheiten hat, Zugehörigkeit ändern und Einheitendifferenz setzen
                        if (element.anzahl > element.Ziel.einheiten)
                        {
                            element.Ziel.spielerzugehoerigkeit = element.spielerzugehoerigkeit;
                            element.Ziel.einheiten = (element.anzahl - element.Ziel.einheiten);
                        }
                        //Wenn Gegner mindestens gleich viele Einheiten hat, Einheitendifferenz setzen
                        else
                        {
                            element.Ziel.einheiten -= element.anzahl;
                        }
                    }
                    //element aus Liste löschen
                    aktuelleSpielfeldwerte.Unterwegsliste.Remove(element);
                }
            }

            //Wenn Spieler Basen angegeben hat, Einheiten hinschicken
            for (int i = 0; i < 2; i++)
            {
                if ( (Playerinput[i].ersteBasis != null) && (Playerinput[i].zweiteBasis != null) )
                {
                    if (Playerinput[i].ersteBasis.verbindungen.Contains(Playerinput[i].zweiteBasis.ID) && Playerinput[i].ersteBasis.einheiten>1)
                    {
                        int dauer = wegzeit(Playerinput[i].ersteBasis.position, Playerinput[i].zweiteBasis.position);
                        float units = Playerinput[i].ersteBasis.einheiten;

                        //Neue Einheiten in jedem Zyklus hinzufügen
                        //basisliste 0.einheiten +=spieler1basenzahl;
                        //basisliste 1.einheiten +=spieler2basenzahl;

                        EinheitenUnterwegs unterwegs = new EinheitenUnterwegs(Playerinput[i].ersteBasis, units, dauer, Playerinput[i].zweiteBasis);
                        // Das Ganze async machen und in Threads auslagern...

                        aktuelleSpielfeldwerte.AddUnterwegs(unterwegs);
                        // Abziehen der Einheiten der ersten Basis
                        Playerinput[i].ersteBasis.einheiten = 0;
                    }
                    else
                    {
                        Debug.WriteLine("Verbindung nicht möglich");
                    }
                    //Ereignis zurücksetzen, um neue Tastatur- / Mauseingabe auszulesen
                    Playerinput[i].ersteBasis = null;
                    Playerinput[i].zweiteBasis = null;
                }
            }

            //neue Informationen über die Unterwegsliste an die Grafikdatensammelklasse Grafikinformationen weitergeben
            if (grafikdatenunterwegslisteupdate != null)
            {
                grafikdatenunterwegslisteupdate(this, new GrafikEventArgs() { actwerte = aktuelleSpielfeldwerte, level = aktuellelevelsettings});
            }
            
            //Teil eine Zeile drüber heißt Initialisierungsliste, spart Argumentübergabe über Konstruktor
        }

        public int wegzeit(koordinaten basis1, koordinaten basis2)
        {
            double x;
            //40.42640 ist 60/sqrt(2) ==> größter WErt von x ist 60
            x=40.42640*(Math.Sqrt(Math.Pow(basis1.x - basis2.x,2) + Math.Pow(basis1.y - basis2.y,2)));
            Debug.WriteLine("gesetzte Anfangswegzeit: " +x);
            return ((int)x);
        }

        #endregion
    }

}
