using QwirkleClassLibrary.Games;
using QwirkleClassLibrary.Players;
using QwirkleClassLibrary.Tiles;
using QwirkleClassLibrary.Events;
using QwirkleClassLibrary.Boards;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.ComponentModel;
using Cell = QwirkleClassLibrary.Boards.Cell;
using Color = Microsoft.Maui.Graphics.Color;
using System.Drawing;
using QwirkleClassLibrary.Persistences;
using CommunityToolkit.Maui.Views;
using System.Diagnostics;

namespace Qwirkle.Pages;

public partial class Gameboard : ContentPage
{
    public ICommand OnDrop => new Command<Cell>(OnDropTile);
    public ICommand OnDropB => new Command(OnDropBag);

    private Game game = ((App)Application.Current!).Game;

    private Tile? tiledrag;

    private List<Tile> tilesSwap = [];

    public Color ColorBC1 { get; set; } = Colors.Transparent;
    public Color ColorBC2 { get; set; } = Colors.Transparent;
    public Color ColorBC3 { get; set; } = Colors.Transparent;
    public Color ColorBC4 { get; set; } = Colors.Transparent;

    public Gameboard()
    {
        InitializeComponent();
        BindingContext = game;

        ChangeColorBC();


    }
    
    private async void Game_EndOfGameNotified(object? sender, EndOfGameNotifiedEventArgs e)
    {
        await PopUpEnd();
        await Navigation.PushAsync(new MainPage());
    }

    private Task PopUpEnd()
    {
        return this.ShowPopupAsync(new PopUpEndGame());
    }

    private void OnDragStarting(object sender, DragStartingEventArgs e)
    {
        var tile = ((Element)sender).BindingContext as Tile;
        e.Data.Text = tile?.ToString();
        tiledrag = tile;
    }

    private void OnDragOver(object sender, DragEventArgs e)
    {
        e.AcceptedOperation = DataPackageOperation.Copy;
    }

    private void OnDragOverBag(object sender, DragEventArgs e)
    {
        e.AcceptedOperation = DataPackageOperation.Copy;
    }


    private void OnDropTile(Cell cell)
    {
        game.PlaceTileNotified += Game_PlaceTileNotified;

        int x = cell.GetX;
        int y = cell.GetY;

        game.PlaceTile(game.GetPlayingPlayer(), tiledrag!, x, y);

        game.PlaceTileNotified -= Game_PlaceTileNotified;
    }

    private void Game_PlaceTileNotified(object? sender, PlaceTileNotifiedEventArgs args)
    {
        if(args.Tile != null)
        {
            DisplayAlert("Tile place notified", args.Tile.ToString() + " : " + args.Reason, "<3");
            return;
        }
        DisplayAlert("Tile place notified", args.Reason, "<3");
    }

    private void OnButtonSkipClicked(object sender, EventArgs e)
    {
        game.NextPlayerNotified += Game_NextPlayerNotified;
        game.EndOfGameNotified += Game_EndOfGameNotified;

        if (game.PlayerSwapping) 
        {
            game.SwapTilesNotified += Game_SwapTilesNotified;
            game.SwapTiles(game.GetPlayingPlayer(), tilesSwap);
            tilesSwap.Clear();
            game.PlayerSwapping = false;
            game.SwapTilesNotified -= Game_SwapTilesNotified;
        }
        else
        {
            var x = game.GetPlayerScore(game.GetPlayingPlayer(), game.CellsUsed, game.GetBoard()!);

            DisplayAlert("TEMP ALERT FOR DEBUG", game.GetPlayingPlayer().ToString() + " win : " + x, "Copy !");

            game.EmptyCellUsed();
            game.DrawTiles(game.GetPlayingPlayer());
        }
        
        game.CheckGameOver(game.GetPlayingPlayer());

        IGamePersistence gameIntermediateSave = new GamePersistenceXml();
        gameIntermediateSave.SaveGame(game);

        if (!game.CheckGameOver(game.GetPlayingPlayer()))
        {
            game.SetNextPlayer();
            ChangeColorBC();
        }
        else
        {
            ((App)Application.Current!).Ld.AddScoreInLead(game.ScoreBoard);

            IGamePersistence gameEndSave = new GamePersistenceXml();
            gameEndSave.SaveGame(game);
            
            ILeaderboardPersistence leaderboardSave = new LeaderboardPersistenceJson();
            leaderboardSave.SaveLeaderboard(((App)Application.Current!).Ld);
            
            game.ClearGame();
        }
        game.NextPlayerNotified -= Game_NextPlayerNotified;
        game.EndOfGameNotified -= Game_EndOfGameNotified;

    }

    private void ChangeColorBC()
    {
        if (game.GetPlayingPlayerPosition() == 0)
        {
            ColorBC1 = Colors.White;
            ColorBC2 = Colors.Transparent;
            ColorBC3 = Colors.Transparent;
            ColorBC4 = Colors.Transparent;
            OnPropertyChanged(nameof(ColorBC1));
            OnPropertyChanged(nameof(ColorBC2));
            OnPropertyChanged(nameof(ColorBC3));
            OnPropertyChanged(nameof(ColorBC4));
        }
        if (game.GetPlayingPlayerPosition() == 1)
        {
            ColorBC2 = Colors.White;
            ColorBC1 = Colors.Transparent;
            ColorBC3 = Colors.Transparent;
            ColorBC4 = Colors.Transparent;
            OnPropertyChanged(nameof(ColorBC1));
            OnPropertyChanged(nameof(ColorBC2));
            OnPropertyChanged(nameof(ColorBC3));
            OnPropertyChanged(nameof(ColorBC4));
        }
        if (game.GetPlayingPlayerPosition() == 2)
        {
            ColorBC3 = Colors.White;
            ColorBC1 = Colors.Transparent;
            ColorBC2 = Colors.Transparent;
            ColorBC4 = Colors.Transparent;
            OnPropertyChanged(nameof(ColorBC1));
            OnPropertyChanged(nameof(ColorBC2));
            OnPropertyChanged(nameof(ColorBC3));
            OnPropertyChanged(nameof(ColorBC4));
        }
        if (game.GetPlayingPlayerPosition() == 3)
        {
            ColorBC4 = Colors.White;
            ColorBC1 = Colors.Transparent;
            ColorBC3 = Colors.Transparent;
            ColorBC2 = Colors.Transparent;
            OnPropertyChanged(nameof(ColorBC1));
            OnPropertyChanged(nameof(ColorBC2));
            OnPropertyChanged(nameof(ColorBC3));
            OnPropertyChanged(nameof(ColorBC4));
        }
    }

    private void Game_NextPlayerNotified(object? sender, NextPlayerNotifiedEventArgs args)
    {
        Debug.WriteLine(args.Player.NameTag);
    }

    private void OnButtonSwapClicked(object sender, EventArgs e)
    {
        game.PlaceTileNotified += Game_PlaceTileNotified;

        if (game.CellsUsed.Count == 0 && !game.PlayerSwapping)
        {
            _ = AnswerSwap();
        }

        game.PlaceTileNotified -= Game_PlaceTileNotified;
    }

    private async Task AnswerSwap()
    {
        bool answer = await DisplayAlert("Swap System", "Are you sure you want to swap your tiles? Attention, if you swap you can not play", "Yes", "No");

            if (answer)
            {
                game.PlayerSwapping = true;
            }
    }

    private void Game_SwapTilesNotified(object? sender, SwapTilesNotifiedEventArgs args)
    {
        DisplayAlert("Swap system", args.Reason, "<3");
    }

    private void OnDropBag()
    {
        if (game.PlayerSwapping)
        {
            game.PlayerList[game.GetPlayingPlayerPosition()].RemoveTileToPlayer(tiledrag!);
            tilesSwap.Add(tiledrag!);
        }
    }

    private async void OnButtonExitClicked(object sender, EventArgs e)
    {
        bool answer = await DisplayAlert("System information", "Are you sure you want to quit? You can resume your game at any time from the home screen.", "Yes", "No");

        if (answer)
        {
            IGamePersistence gameIntermediateSave = new GamePersistenceXml();
            gameIntermediateSave.SaveGame(game);


            game.ClearGame();
            await Navigation.PopToRootAsync();
            
        }
    }

    private void OnButtonBookClicked(object? sender, EventArgs e)
    {
        Navigation.PushAsync(new Rules());
    }

    private void OnButtonSettingsClicked(object? sender, EventArgs e)
    {
        Navigation.PushAsync(new Settings());
    }


}
