using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using YatzyGame.Components;
using YatzyGame.Models;

namespace YatzyGame.Controllers;

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;

    private readonly MultiplayerController multiplayerController;

    private readonly MyApp.WebSockets.WebSocketManager webSocketManager;

    public HomeController(ILogger<HomeController> logger, MultiplayerController multiplayerController, MyApp.WebSockets.WebSocketManager webSocketManager)
    {
        _logger = logger;
        this.multiplayerController = multiplayerController;
        this.webSocketManager = webSocketManager;
    }

    public IActionResult Index()
    {
        return View();
    }

    [Route("CreateGame/{type}/{name}")]
    [Route("CreateGame/{type}")]
    public IActionResult CreateGame(int type, string name)
    {
        string id = string.Empty;

        var playerId = Guid.NewGuid().ToString();

        Response.Cookies.Append("playerID", playerId);

        switch (type)
        {
            case 0:
                id = multiplayerController.CreateGame(true, name, playerId);
                break;
            case 1:
                id = multiplayerController.CreateGame(false, name, playerId);
                break;
            default:
                break;
        }
        ;

        if (string.IsNullOrEmpty(id))
        {
            return RedirectToAction(nameof(Index));
        }

        return RedirectToAction(nameof(Game), new { id = id });
    }

    [Route("Game/{id}/")]
    public IActionResult Game(string id)
    {
        var specificGameController = multiplayerController.GetGameController(id);

        var retval = specificGameController != null ? new HomeViewModel(specificGameController, Request.Cookies["playerID"]) : new HomeViewModel();

        return View(retval);
    }

    [HttpPost]
    [Route("Game/{game}/AddPlayer")]
    public async Task<IActionResult> AddPlayerAsync(string game, string name)
    {
        multiplayerController.GetGameController(game).AddPlayer(name);

        // gameController.AddPlayer(name);
        await webSocketManager.BroadcastAsync(game + "|update");

        return RedirectToAction(nameof(Game), new { id = game });
    }

    [HttpPost]
    [Route("Game/{game}/Leave")]
    public async Task<IActionResult> LeaveGame(string game, string name)
    {
        multiplayerController.GetGameController(game).RemovePlayer(name);

        // gameController.AddPlayer(name);
        await webSocketManager.BroadcastAsync(game + "|update");

        return RedirectToAction(nameof(Index));
    }

    [HttpPost]
    [Route("Game/{game}/SelectDice/{id}")]
    public async Task<IActionResult> SelectDiceAsync(string game, int id)
    {
        multiplayerController.GetGameController(game).SelectDice(id);

        // gameController.SelectDice(id);
        
        await webSocketManager.BroadcastAsync(game + "|update");
        return RedirectToAction(nameof(Game), new { id = game });
    }

    [HttpPost]
    [Route("Game/{game}/RerollSelected")]
    public async Task<IActionResult> RerollSelected(string game)
    {
        multiplayerController.GetGameController(game).RerollSelected();
        await webSocketManager.BroadcastAsync(game + "|update");
        return RedirectToAction(nameof(Game), new { id = game });
    }

    [Route("Game/{game}/InsertDice/{id}")]
    public async Task<IActionResult> InsertDiceAsync(string game, string id)
    {
        multiplayerController.GetGameController(game).InsertPoint(id, multiplayerController.GetGameController(game).Dices.Select(x => x.Value).ToList());

        await webSocketManager.BroadcastAsync(game + "|update");
        return RedirectToAction(nameof(Game), new { id = game });
    }

    [Route("Game/{game}/DeletePlayer/{id}")]
    public async Task<IActionResult> DeletePlayerAsync(string game, string id)
    {
        multiplayerController.GetGameController(game).RemovePlayer(id);

        await webSocketManager.BroadcastAsync(game + "|update");
        return RedirectToAction(nameof(Game), new { id = game });
    }

    [HttpPost]
    [Route("Game/{game}/StartGame")]
    public async Task<IActionResult> StartGameAsync(string game)
    {
        multiplayerController.GetGameController(game).startGame();
        await webSocketManager.BroadcastAsync(game + "|update");
        return RedirectToAction(nameof(Game), new { id = game });
    }

    [HttpPost]
    [Route("Game/{game}/StopGame")]
    public async Task<IActionResult> StopGameAsync(string game)
    {
        multiplayerController.GetGameController(game).stopGame();
        await webSocketManager.BroadcastAsync(game + "|update");
        return RedirectToAction(nameof(Game), new { id = game });
    }

    [HttpGet]
    [Route("Game/Join/{joinCode}")]
    [Route("Game/Join")]
    public IActionResult JoinGame(string joinCode)
    {
        Response.Cookies.Delete("playerID");
        var controller = multiplayerController.GetGameControllerFromJoinCode(joinCode);

        if (controller.gameStarted)
        {
            return RedirectToAction(nameof(Index));
        }

        return View(null, controller.gameID);
    }

    [HttpPost]
    [Route("Game/Join/{gameId}")]
    public async Task<IActionResult> JoinGameAsync(string gameId, string name)
    {
        if (Request.Cookies["playerID"] != null && multiplayerController.playerGameControllerRelation.ContainsKey(Request.Cookies["playerID"]))
        {
            var gameID = multiplayerController.GetPlayerGameController(Request.Cookies["playerID"]).gameID;
            if (!string.IsNullOrEmpty(gameID))
            {
                return RedirectToAction(nameof(Game), new { id = gameID });
            }

            Response.Cookies.Delete("playerID");
        }

        var playerId = Guid.NewGuid().ToString();

        Response.Cookies.Append("playerID", playerId);

        multiplayerController.CreatePlayer(gameId, playerId, name);
        await webSocketManager.BroadcastAsync(gameId + "|update");
        return RedirectToAction(nameof(Game), new { id = gameId });
    }

    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
    public IActionResult Error()
    {
        return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
    }
}
public class HomeViewModel
{
    public HomeViewModel() { }
    public HomeViewModel(GameController gameController, string playerId)
    {
        this.players = gameController.GetPlayers();
        this.GameStarted = gameController.gameStarted;
        this.Dices = gameController.Dices;
        this.selectedDices = gameController.selectedDices;
        this.CurrentPlayer = gameController.currentPlayer;
        this.RerollsBlocked = gameController.rerolls <= 0;
        this.gameID = gameController.gameID;
        this.joinCode = gameController.joinCode;
        this.onlineMultiplayer = gameController.onlineMultiplayer;

        this.player = gameController.GetPlayerById(playerId);

    }

    public List<Player> players { get; set; }
    public bool GameStarted { get; set; }
    public Dictionary<int, int> Dices { get; set; }
    public List<int> selectedDices { get; set; }
    public Player CurrentPlayer { get; set; }
    public Player player { get; set; }
    public bool RerollsBlocked { get; set; }
    public int playerCount { get; set; }
    public string gameID { get; set; }
    public string joinCode { get; set; }
    public bool onlineMultiplayer { get; set; }
} 
