using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Reflection.Metadata;
using System.Xml;
using Jypeli;
using Jypeli.Assets;
using Jypeli.Controls;
using Jypeli.Widgets;
using SixLabors.ImageSharp.Memory;

namespace Lokkihunter;

/// @author sulasaal
/// @version 23.10.2023
/// <summary>
/// 
/// </summary>
public class Lokkihunter : PhysicsGame
{
    private static readonly string[] kentta0 = {
        "                        ",
        "                        ",
        "                    o   ",
        "                        ",
        "   v                    ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "           A            ",
    };
    
    private static readonly string[] kentta1 = {
        "                        ",
        "                        ",
        "                    o   ",
        "                        ",
        "   v                    ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "           A            ",
    };
    
    private static readonly string[] kentta2 = {
        "                        ",
        "                        ",
        "                    o   ",
        "                        ",
        "   v                    ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "           A            ",
    };
    
    private static readonly string[] kentta3 = {
        "                        ",
        "                        ",
        "                    o   ",
        "                        ",
        "   v                    ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "           A            ",
    };
    
    private static readonly string[] kentta4 = {
        "                        ",
        "                        ",
        "                    o   ",
        "                        ",
        "   v                    ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "           A            ",
    };
    
    private static readonly string[] kentta5 = {
        "                        ",
        "                        ",
        "                    o   ",
        "                        ",
        "   v                    ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "           A            ",
    };
    
    private static readonly string[] kentta6 = {
        "                        ",
        "                        ",
        "                    o   ",
        "                        ",
        "   v                    ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "           A            ",
    };
    
    private static readonly string[] kentta7 = {
        "                        ",
        "                        ",
        "                    o   ",
        "                        ",
        "   v                    ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "           A            ",
    };
    
    private static readonly string[] kentta8 = {
        "                        ",
        "                        ",
        "                    o   ",
        "                        ",
        "   v                    ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "           A            ",
    };
    
    private static readonly string[] kentta9 = {
        "                        ",
        "                        ",
        "                    o   ",
        "                        ",
        "   v                    ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "                        ",
        "           A            ",
    };

    private static readonly string[][] kenttalista =
        { kentta0, kentta1, kentta2, kentta3, kentta4, kentta5, kentta6, kentta7, kentta8, kentta9, kentta9 };
    private static readonly Color[] ylaVarit = { Color.White, Color.LightYellow, Color.LightPink, Color.LightGreen };
    private static readonly Color[] alaVarit = { Color.Blue, Color.Blue, Color.Blue, Color.Blue };

    private static int tileWidth;
    private static int tileHeight;
    
    readonly Vector nopeusVasen = new Vector(200, 0);
    readonly Vector nopeusOikea = new Vector(-200, 0);
    
    
    private PhysicsObject pekka;
    private PhysicsObject lokkiVasen;
    private PhysicsObject lokkiOikea;
    
    AssaultRifle pekkaAse;
    
    PhysicsObject oikeaReuna;
    PhysicsObject vasenReuna;
    
    
    private readonly IntMeter kenttaNro = new IntMeter(0, 0, 10);
    // private const int kenttaNro = 1;


    public override void Begin()
    { 
        
        UusiPeli();
        AsetaOhjaimet();
    }

    void UusiPeli()
    {
        kenttaNro.Value = 0;
        SeuraavaKentta();
    }
    
    
    void AsetaOhjaimet()
    {
        Keyboard.Listen(Key.F1, ButtonState.Pressed, ShowControlHelp, "Show help");
        Keyboard.Listen(Key.F5, ButtonState.Pressed, Begin, "New game");
        
        PhoneBackButton.Listen(ConfirmExit, "Lopeta peli");
        Keyboard.Listen(Key.Escape, ButtonState.Pressed, ConfirmExit, "Lopeta peli");
        
        Keyboard.Listen(Key.D,ButtonState.Down, AsetaNopeusPekka, "Pekka: Liikkuu vasemmalle", pekka, nopeusVasen);
        Keyboard.Listen(Key.D, ButtonState.Released, AsetaNopeusPekka, null, pekka, Vector.Zero);

        Keyboard.Listen(Key.A,ButtonState.Down, AsetaNopeusPekka, "Pekka: Liikkuu oikealle", pekka, nopeusOikea);
        Keyboard.Listen(Key.A, ButtonState.Released, AsetaNopeusPekka, null, pekka, Vector.Zero);
        
        Mouse.Listen(MouseButton.Left, ButtonState.Down, AmmuAseella, "Ammu", pekkaAse);
        
        Mouse.ListenMovement(0.1, Tahtaa, "Tähtää aseella");
    }

    
    void SeuraavaKentta()
    {
        // ClearAll();
        // string[] kentankuva = kenttalista.Length;
        // for (int kenttaNro = 1; kenttaNro <= kenttalista.Length; kenttaNro++)
        // {
        //     if (kenttaNro > kenttalista.Length) Exit();
        //     
        //     LuoKentta($"kentta{kenttaNro}");
        // }
        kenttaNro.Value++;
        if (kenttaNro.Value > kenttalista.Length)
        {
            // NaytaIlmoitus("All levels completed!", Color.Yellow);
            return;
        }
        ClearAll();
        int index = kenttaNro.Value - 1;
        string[] tasonKuva = kenttalista[index];
        if (index >= alaVarit.Length) index = alaVarit.Length - 1;
        Level.Background.CreateGradient(alaVarit[index], ylaVarit[index]);
        
        Level.Background.CreateGradient(Color.Green, Color.White);
        
        tileWidth = 800 / tasonKuva[0].Length;
        tileHeight = 480 / kenttalista.Length;
        var tiles = TileMap.FromStringArray(tasonKuva);
                
        tiles.SetTileMethod('A', LuoPekka, Color.Wheat);
        tiles.SetTileMethod('v', LuoLokkiVasen, Color.Black);
        tiles.SetTileMethod('o', LuoLokkiOikea, Color.Black);
        
        tiles.Execute(tileWidth, tileHeight);
        
        // alaReuna = Level.CreateBottomBorder(1, false);
        // alaReuna.IgnoresExplosions = true;
        // Add(alaReuna);
       
        // ylaReuna = Level.CreateTopBorder(1, false);
        // ylaReuna.IgnoresExplosions = true;
        // Add(ylaReuna);
        
        oikeaReuna = Level.CreateRightBorder(1.0, false);
        oikeaReuna.Height = 1000;
        oikeaReuna.X = 550;
        oikeaReuna.Restitution = 1.0;
        
        vasenReuna = Level.CreateLeftBorder(1.0, false);
        vasenReuna.Height = 1000;
        vasenReuna.X = -550;
        vasenReuna.Restitution = 1.0;
        
        Camera.ZoomToLevel();
    }
    
    
    /// <summary>
    /// Aliohjelma luo Pekan ja antaa sille aseen.
    /// </summary>
    private void LuoPekka(Vector paikka, double leveys, double korkeus, Color vari)
    {
        pekka = new PhysicsObject(40.0, 40.0)
        {
            Shape = Shape.Circle,
            Restitution = 1.0,
            Color = vari,
            Position = paikka,
            Tag = "pelaaja"
        };
        Add(pekka);

        pekkaAse = new AssaultRifle(40, 10)
        {
            Ammo =
            {
                Value = 100
            },
            FireRate = 5.0,
            ProjectileCollision = AmmusOsui,
            Position = pekka.Position + new Vector(pekka.Width / 2, 0),
            Angle = Angle.FromDegrees(90)
        };

        pekka.Add(pekkaAse);
    }
    
    
    /// <summary>
    /// Mitä tapahtuu kun ammus osuu lokkiin
    /// </summary>
    /// <param name="ammus">ammus</param>
    /// <param name="kohde">eka mitä ammutaan</param>
    private void AmmusOsui(PhysicsObject ammus, PhysicsObject kohde)
    {
        Explosion rajahdys = new Explosion(50)
        {
            Position = kohde.Position
        };
        Add(rajahdys);

        ammus.Destroy();
        kohde.Destroy();
    }
    
    
    /// <summary>
    /// Aliohjelma aseella ampumiseen
    /// </summary>
    /// <param name="ase">millä ammutaan</param>
    void AmmuAseella(AssaultRifle ase)
    {
        PhysicsObject ammus = ase.Shoot();

        if (ammus != null)
        {
            ammus.Size *= 4;
            // ammus.Image = ...
            ammus.MaximumLifetime = TimeSpan.FromSeconds(2.0);
        }
    }
    
    
    /// <summary>
    /// Aliohjelma aseella tähtäämiseen hiirellä
    /// </summary>
    void Tahtaa()
    {
        Vector suunta = (Mouse.PositionOnWorld - pekkaAse.AbsolutePosition).Normalize();
        pekkaAse.Angle = suunta.Angle;
    }
    
    
    /// <summary>
    /// asettaa pekalle nopuden.
    /// </summary>
    /// <param name="_pekka">mitä oliota liikutetaan</param>
    /// <param name="nopeus">millä nopeudella</param>
    public void AsetaNopeusPekka(PhysicsObject _pekka, Vector nopeus)
    {
        pekka.Velocity = nopeus;
    }

    
/// <summary>
/// Aliohjelma luo lokin
/// </summary>
/// <returns></returns>
    private static PhysicsObject LuoLokki()
    {
        PhysicsObject lokki = new PhysicsObject(60.0, 20.0)
        {
            Shape = Shape.Rectangle,
            Restitution = 1.0
        };
        // lokki.Image = ...
        return lokki;
    }


    void LokkiLentaa(PhysicsObject lentaja, double vx)
    {
        lentaja.Hit(new Vector(vx, 0.0));
    }

/// <summary>
/// Luodaan vasemmanpuoleinen lokki ja annetaan sille jokin satunnainen y-koordinaatin arvo.
/// </summary>
/// <param name="position"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="lokki"></param>
    private void LuoLokkiVasen(Vector position, double width, double height, Color lokki)
{
        lokkiVasen = LuoLokki();
        LokkiLentaa(lokkiVasen, 150);
        lokkiVasen.Y = RandomGen.NextDouble(200, 350);
        lokkiVasen.Tag = "vasenlokki";
        lokkiVasen.Restitution = 1.0;
        Add(lokkiVasen);
    }

    /// <summary>
    /// Luo oikeanpuoleisenlokin ja annetaan sille jokin satunnainen y-koordinaatti, mikä on eri
    /// kuin vasemmanpuoleisen lokin.
    /// </summary>
    /// <param name="position"></param>
    /// <param name="width"></param>
    /// <param name="height"></param>
    /// <param name="lokki"></param>
    private void LuoLokkiOikea(Vector position, double width, double height,Color lokki)
    {
        lokkiOikea = LuoLokki();
        LokkiLentaa(lokkiOikea, -150);
        double y;
        do
        {
            y = RandomGen.NextDouble(200, 350);
        } 
        while (Math.Abs(y - lokkiVasen.Y) < 40);
        lokkiOikea.Y = y;
        lokkiOikea.Tag = "oikealokki";
        lokkiOikea.Restitution = 1.0;
        Add(lokkiOikea);
    }
    
    // void LisaaLaskurit()
    // {
    //     kentanNro = LuoPisteLaskuri(Screen.Left + 100.0, Screen.Top - 100.0);
    // }
    //
    // IntMeter LuoPisteLaskuri(double x, double y)
    // {
    //     IntMeter laskuri = new IntMeter(0);
    //     laskuri.MaxValue = 10;
    //
    //     Label naytto = new Label();
    //     naytto.BindTo(laskuri);
    //     naytto.X = x;
    //     naytto.Y = y;
    //     naytto.TextColor = Color.White;
    //     naytto.BorderColor = Level.Background.Color;
    //     naytto.Color = Level.Background.Color;
    //     Add(naytto);
    //     
    //     return laskuri;
    // }
    //
    
    // törmäys vasen ja oikea reuna
    // pisteeta
    // kentät
    // kommentit koodiin
    // alkuvalikko
}