using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace CSharpProjekt {
    public class Kampf
    {
        Spieler angreifer;
        Spieler verteidiger;
        bool verteidigen = true;
        bool stadtAngreifen;
        int kampfKraftAngreifer;
        int kampfKraftVerteidiger;
        Random rand;
        int angriffsBonus = 0;
        bool untertunnelt = false;

        public Kampf(Spieler angreifer, int angriffsBonus, bool untertunnelt) {
            this.angreifer = angreifer;
            this.verteidiger = angreifer.Gegner;
            this.angriffsBonus = angriffsBonus;
            this.untertunnelt = untertunnelt;
            rand = new Random();
            AngriffDurchfuehren();
            angreifer.Armee.Regenerieren();
            verteidiger.Armee.Regenerieren();
        }

        public void AngriffDurchfuehren () {
            MessageBoxButtons buttons = MessageBoxButtons.YesNo;
            MessageBoxIcon icon = MessageBoxIcon.Question;
            if (angreifer.Armee.Einheiten.Count <= 0) {
                MessageBox.Show("Angriff ohne Einheiten nicht möglich!");
                return;
            }
            if (verteidiger.Armee.Einheiten.Count > 0) {
                DialogResult result = MessageBox.Show(verteidiger.Control, "Gegner auf offenem Feld bekämpfen?", verteidiger.Name, buttons, icon);
                verteidigen = result == DialogResult.Yes ? true : false;
            } else
                verteidigen = false;
            if (verteidigen)
                Kaempfen();
            else {
                DialogResult result = MessageBox.Show(angreifer.Control, "Stadt angreifen?", angreifer.Name, buttons, icon);
                stadtAngreifen = result == DialogResult.Yes ? true : false;
                if (stadtAngreifen)
                    Belagern();
                else
                    Brandschatzen();
            }
        }

        public void Kaempfen() {
            kampfKraftAngreifer = angreifer.Armee.AngriffsPunkte() + angriffsBonus;
            kampfKraftVerteidiger = verteidiger.Armee.VersteidigungsPunkte();
            int ergebnis = kampfKraftAngreifer - kampfKraftVerteidiger;
            Spieler verlierer = kampfKraftAngreifer < kampfKraftVerteidiger ? angreifer : verteidiger;
            int[] angreiferVerluste = angreifer.Armee.VerlusteErleiden(kampfKraftVerteidiger, rand);
            int[] verteidigerVerluste = verteidiger.Armee.VerlusteErleiden(kampfKraftAngreifer, rand);
            int[] verfolgungsVerluste = verlierer.Armee.VerlusteErleiden(verlierer.Gegner.Armee.VerfolgungsPunkte(), rand);

            StringBuilder msg = new StringBuilder();
            msg.Append("Kampfkraft " + angreifer.Name + ": " + kampfKraftAngreifer + ", " + "Kampfkraft " + verteidiger.Name + ": " + kampfKraftVerteidiger + "\n");
            msg.Append(verlierer.Gegner.Name + " hat den Kampf gewonnen\n");
            msg.Append(KampfergebnisStringFormatieren(angreifer, angreiferVerluste, false) + "\n");
            msg.Append(KampfergebnisStringFormatieren(verteidiger, verteidigerVerluste, false) + "\n");
            msg.Append(KampfergebnisStringFormatieren(verlierer, verfolgungsVerluste, true));

            MessageBox.Show(msg.ToString());
        }

        public void Belagern() {
            int schadenAnStadt = 0;
            int[] angreiferVerluste = {0, 0, 0};
            int[] verteidigerVerluste = {0, 0, 0};
            kampfKraftAngreifer = angreifer.Armee.BelagerungsPunkte() - (untertunnelt ? 0 : verteidiger.Mauer) + angriffsBonus;
            kampfKraftVerteidiger = verteidiger.Armee.StadtVerteidigungsPunkte() + (untertunnelt ? 0 : verteidiger.Mauer);
            if (verteidiger.Armee.Einheiten.Count > 0) {
                int ergebnis = kampfKraftAngreifer - kampfKraftVerteidiger;
                angreiferVerluste = angreifer.Armee.VerlusteErleiden(kampfKraftVerteidiger, rand);
                if (kampfKraftAngreifer > 0) {
                    schadenAnStadt = rand.Next(kampfKraftAngreifer / 2 + 1);
                    verteidigerVerluste = verteidiger.Armee.VerlusteErleiden(kampfKraftAngreifer - schadenAnStadt, rand);
                }
            } else { // Verteidiger hat keine Einheiten
                schadenAnStadt = kampfKraftAngreifer;
            }
            verteidiger.StadtBeschädigen(schadenAnStadt, untertunnelt);

            StringBuilder msg = new StringBuilder();
            msg.Append("Kampfkraft " + angreifer.Name + ": " + kampfKraftAngreifer + ", " + "Kampfkraft " + verteidiger.Name + ": " + kampfKraftVerteidiger + "\n");
            msg.Append("Schaden an Stadt: " + schadenAnStadt + "\n");
            msg.Append(KampfergebnisStringFormatieren(angreifer, angreiferVerluste, false) + "\n");
            msg.Append(KampfergebnisStringFormatieren(verteidiger, verteidigerVerluste, false) + "\n");

            MessageBox.Show(msg.ToString());
        }

        /// <summary>
        /// Für jede zu zerstörende Produktionsstätte wird eine zufällig ausgewählte, wobei jede existierende Produktionsstätte die gleiche Wahrscheinlichkeit
        /// hat ausgewählt zu werden. Gibt es also z.B. gerade 4 Felder, 2 Goldminen und keine Steinbrüche, dann wird als nächstes mit Wahrscheinlichkeit 2/3 ein Feld zerstört.
        /// </summary>
        public void Brandschatzen() {
            int indexZuZerstören;
            int anzahlZuZerstören = angreifer.Armee.Einheiten.Count/3 + 1;
            for (int i = 0; i < anzahlZuZerstören; i++) {
                if (verteidiger.Prod[(int)Produktion.feld] <= 0 && verteidiger.Prod[(int)Produktion.mine] <= 0 && verteidiger.Prod[(int)Produktion.steinbruch] <= 0)
                    return;
                
                int indexFeld = verteidiger.Prod[(int)Produktion.feld];
                int indexMine = indexFeld + verteidiger.Prod[(int)Produktion.mine];
                int indexSteinbruch = indexMine + verteidiger.Prod[(int)Produktion.steinbruch];
                indexZuZerstören = rand.Next(1, indexSteinbruch);
                if (indexZuZerstören <= indexFeld)
                    verteidiger.Prod[(int)Produktion.feld]--;
                else if (indexZuZerstören <= indexMine)
                    verteidiger.Prod[(int)Produktion.mine]--;
                else
                    verteidiger.Prod[(int)Produktion.steinbruch]--;
            }
        }

        public String KampfergebnisStringFormatieren(Spieler spieler, int[] verlusteFürSpieler, bool verfolgung) {
            StringBuilder msg = new StringBuilder();

            msg.Append(verfolgung ? spieler.Name + " flieht und wird von " + spieler.Gegner.Name + " verfolgt. Auf der Flucht getötete Einheiten: " : "Verlorene Einheiten für " + spieler + ": ");
            if (verlusteFürSpieler[0] > 0)
                msg.Append(verlusteFürSpieler[0] + " Schwertkämpfer");
            if (verlusteFürSpieler[1] > 0)
                msg.Append((verlusteFürSpieler[0] > 0 ? ", " : String.Empty) + verlusteFürSpieler[1] + " Bogenschütze");
            if (verlusteFürSpieler[2] > 0)
                msg.Append((verlusteFürSpieler[0] > 0 || verlusteFürSpieler[1] > 0 ? ", " : String.Empty) + verlusteFürSpieler[2] + " Ritter");
            if (verlusteFürSpieler[0] == 0 && verlusteFürSpieler[1] == 0 && verlusteFürSpieler[2] == 0)
                msg.Append("keine");

            return msg.ToString();
        }
    }
}
