/*
Autori: 
    Adrians Zemturis 110
    Ingus Zemturis 110

IDE: 
    Visual Studio Community 2026
 */

using System;

namespace RPG_game
{
    internal class Program
    {
        // Komandu lietas
        static private Team FirstTeam = new Team() { };
        static private Team SecondTeam = new Team() { };
        private struct Team
        {
            public Player Class1;
            public Player Class2;
        }
        // Spēlētāju klases
        private abstract class Player
        {
            public string Name; // Vārds
            public float MaxHP; // Maksimālie dzīves punkti
            public float HP; // Dzīves punkti
            public float DR; // (Damage Reduction) Bojājumu samazināšana
            public float DMGB; // Uzbrukumu pastiprinājums
            public float MaxENG; // Maksimālā energija
            public float ENG; // Energija
            public float ENGR; // Energijas atjaunināšana 
            public Ability FirstAbility; // Pirmā spēja
            public Ability SecondAbility; // Otrā spēja
            public void TakeDamage(float DMG) {
                // DR vērtība ir 0 līdz 1, un DMG vērtībai ir jau izrēķināts DMGB
                this.HP = Math.Clamp(this.HP - (DMG * (1 - this.DR)), 0, this.MaxHP);
            }
        }

        private class Warrior : Player
        {
            public Warrior()
            {
                this.Name = "Warrior";
                this.MaxHP = 200;
                this.HP = 200;
                this.DR = 0.15f;
                this.DMGB = 0.2f;
                this.MaxENG = 80;
                this.ENG = 80;
                this.ENGR = 6;
                this.FirstAbility = new Slash();
                this.SecondAbility = new CycloneSlash();
            }
        }

        private class Mage : Player
        {
            public Mage()
            {
                this.Name = "Mage";
                this.HP = 150;
                this.MaxHP = 150;
                this.DR = 0f;
                this.DMGB = 0.35f;
                this.MaxENG = 120;
                this.ENG = 120;
                this.ENGR = 11;
                this.FirstAbility = new MagicBolt();
                this.SecondAbility = new ManaLance();
            }
        }

        private class Saint : Player
        {
            public Saint()
            {
                this.Name = "Saint";
                this.HP = 150;
                this.MaxHP = 150;
                this.DR = 0.1f;
                this.DMGB = 0.1f;
                this.MaxENG = 100;
                this.ENG = 100;
                this.ENGR = 8;
                this.FirstAbility = new Blessing();
                this.SecondAbility = new Smite();
            }
        }

        private class Tank : Player
        {
            public Tank()
            {
                this.Name = "Tank";
                this.HP = 350;
                this.MaxHP = 350;
                this.DR = 0.2f;
                this.DMGB = 0f;
                this.MaxENG = 80;
                this.ENG = 80;
                this.ENGR = 6;
                this.FirstAbility = new Sacrifice();
                this.SecondAbility = new ShieldBash();
            }
        }

        // Spēju klases
        private abstract class Ability()
        {
            public string Name; // Spēju vārds
            public string DESC; // Spēju apraksts
            public float VAL; // Vērtiba kuru izmantos spēju Attack() funkcija
            public float ENGC; // Energijas maksa

            // PLR1 ir spēlētāju klase kuru lietotājs izvēlējas, PLR2 ir lietotāja otrā klase
            // Enemy1 ir pretinieks kuru lietotājs izvēlējās
            // PLR2 un Enemy2 ir piedāvāti priekš dažām multi-sitienu/komandu dziedināšana uzbrukumiem
            public virtual void Attack(Player PLR1, Player PLR2, Player Enemy1, Player Enemy2) {
                if (this.CanAttack(PLR1))
                {
                    PLR1.ENG -= this.ENGC;
                    float DMG = this.VAL * (1 + PLR1.DMGB);
                    Enemy1.TakeDamage(DMG);
                }
            }
            public bool CanAttack( Player PLR )
            {
                if (PLR.ENG >= this.ENGC)
                {
                    return true;
                } else
                {
                    return false;
                }
            }
        }
        // Warrior klasei
        private class Slash : Ability
        {
            public Slash()
            {
                this.Name = "Slash";
                this.DESC = "Single target slash";
                this.VAL = 16;
                this.ENGC = 5;
            }
        }

        private class CycloneSlash : Ability
        {
            public CycloneSlash()
            {
                this.Name = "Cyclone Slash";
                this.DESC = "Multi target slash";
                this.VAL = 25;
                this.ENGC = 30;
            }
        }
        // Mage klasei
        private class MagicBolt : Ability
        {
            public MagicBolt()
            {
                this.Name = "Magic bolt";
                this.DESC = "Single target magic bolt";
                this.VAL = 20;
                this.ENGC = 8;
            }
        }
        private class ManaLance : Ability
        {
            public ManaLance()
            {
                this.Name = "Mana Lance";
                this.DESC = "Single target mana lance";
                this.VAL = 65;
                this.ENGC = 65;
            }
        }
        // Saint klasei
        private class Blessing : Ability
        {
            public Blessing()
            {
                this.Name = "Blessing";
                this.DESC = "Multi target team heal";
                this.VAL = 40;
                this.ENGC = 50;
            }
            public override void Attack(Player PLR1, Player PLR2, Player Enemy1, Player Enemy2)
            {
                if (this.CanAttack(PLR1))
                {
                    PLR1.ENG -= this.ENGC;
                    PLR1.TakeDamage(-this.VAL);
                    PLR2.TakeDamage(-this.VAL);
                }
            }
        }
        private class Smite : Ability
        {
            public Smite()
            {
                this.Name = "Smite";
                this.DESC = "Multi target smite";
                this.VAL = 12;
                this.ENGC = 10;
            }
        }
        // Tank klasei
        private class Sacrifice : Ability
        {
            public Sacrifice()
            {
                this.Name = "Sacrifice";
                this.DESC = $"Single target ally heal for {this.VAL*2} but the tank takes {this.VAL} dmg";
                this.VAL = 40;
                this.ENGC = 60;
            }
            public override void Attack(Player PLR1, Player PLR2, Player Enemy1, Player Enemy2)
            {
                if (this.CanAttack(PLR1))
                {
                    PLR1.ENG -= this.ENGC;
                    PLR1.TakeDamage(this.VAL);
                    PLR2.TakeDamage(-2*this.VAL);
                }
            }
        }
        private class ShieldBash : Ability
        {
            public ShieldBash()
            {
                this.Name = "Shield Bash";
                this.DESC = "Single target shield bash";
                this.VAL = 12;
                this.ENGC = 2;
            }
        }
        static void Main(string[] args)
        {
            string Stage = "TeamSelect";
            while (true)
            {
                Console.Clear();
                if (Stage == "TeamSelect")
                {
                    int Class1 = 0;
                    int Class2 = 0;
                    Console.WriteLine("Input first teams first class by typing one of the following numbers:\n");
                    Console.WriteLine("(1) Warrior\n(2) Mage\n(3) Saint\n(4) Tank\n");
                    if (int.TryParse(Console.ReadLine(), out Class1) == false) {
                        continue; // Izlaiž ja TryParse atgriež false
                    }
                    Console.Clear();
                    Console.WriteLine("Input first teams second class by typing one of the following numbers:\n");
                    Console.WriteLine("(1) Warrior\n(2) Mage\n(3) Saint\n(4) Tank\n");
                    if (int.TryParse(Console.ReadLine(), out Class2) == false)
                    {
                        continue; // Izlaiž ja TryParse atgriež false
                    }
                    
                    // Pirmās klase izvēlēšana
                    switch(Class1)
                    {
                        case 1:
                            FirstTeam.Class1 = new Warrior();
                            break;
                        case 2:
                            FirstTeam.Class1 = new Mage();
                            break;
                        case 3:
                            FirstTeam.Class1 = new Saint();
                            break;
                        case 4:
                            FirstTeam.Class1 = new Tank();
                            break;
                        default:
                            continue; // Izlaiž ja ievada numuru kas ir < 0 vai > 4
                    }
                    // Otrās klases izvēlēšana
                    switch (Class2)
                    {
                        case 1:
                            FirstTeam.Class2 = new Warrior();
                            break;
                        case 2:
                            FirstTeam.Class2 = new Mage();
                            break;
                        case 3:
                            FirstTeam.Class2 = new Saint();
                            break;
                        case 4:
                            FirstTeam.Class2 = new Tank();
                            break;
                        default:
                            continue; // Izlaiž ja ievada numuru kas ir < 0 vai > 4
                    }

                    // Otrās komandas klases izvēlēšana
                    Console.Clear();
                    Console.WriteLine("Input second teams first class by typing one of the following numbers:\n");
                    Console.WriteLine("(1) Warrior\n(2) Mage\n(3) Saint\n(4) Tank\n");
                    if (int.TryParse(Console.ReadLine(), out Class1) == false)
                    {
                        continue; // Izlaiž ja TryParse atgriež false
                    }
                    Console.Clear();
                    Console.WriteLine("Input second teams second class by typing one of the following numbers:\n");
                    Console.WriteLine("(1) Warrior\n(2) Mage\n(3) Saint\n(4) Tank\n");
                    if (int.TryParse(Console.ReadLine(), out Class2) == false)
                    {
                        continue; // Izlaiž ja TryParse atgriež false
                    }

                    // Pirmās klase izvēlēšana
                    switch (Class1)
                    {
                        case 1:
                            SecondTeam.Class1 = new Warrior();
                            break;
                        case 2:
                            SecondTeam.Class1 = new Mage();
                            break;
                        case 3:
                            SecondTeam.Class1 = new Saint();
                            break;
                        case 4:
                            SecondTeam.Class1 = new Tank();
                            break;
                        default:
                            continue; // Izlaiž ja ievada numuru kas ir < 0 vai > 4
                    }
                    // Otrās klases izvēlēšana
                    switch (Class2)
                    {
                        case 1:
                            SecondTeam.Class2 = new Warrior();
                            break;
                        case 2:
                            SecondTeam.Class2 = new Mage();
                            break;
                        case 3:
                            SecondTeam.Class2 = new Saint();
                            break;
                        case 4:
                            SecondTeam.Class2 = new Tank();
                            break;
                        default:
                            continue; // Izlaiž ja ievada numuru kas ir < 0 vai > 4
                    }
                }
            }            
        }
    }
}