using Common.Library;
using Gready_Poang.Core;
using Gready_Poang.DataLayer;
using Gready_Poang.EntityLayer;
using Gready_Poang.Services;
using System.Collections.ObjectModel;
using System.Diagnostics;

namespace Gready_Poang.ViewModelLayer;

public class RoundRunningViewModel : ViewModelBase
{

    public event EventHandler RebuildRequested;

    public RoundRunningViewModel() : base()
    {
    }

    public RoundRunningViewModel(

        IRepository<GameRound> roundsRepo,
        IRepository<GamePoint> pointsRepo,
        IMethodSharingService<Participant> sharingService,
        ICombinedRepository combined,
        IObjectMessageService objectMessage,
        ISplashService splashService,
        AppShellViewModel appShell
        ) : base()
    {
        _roundsRepo = roundsRepo;
        _pointsRepo = pointsRepo;
        _sharingService = sharingService;
        _combined = combined;
        _objectMessage = objectMessage;
        _splashService = splashService;
        _appShell = appShell;
        _roundElements = new ObservableCollection<RoundBuilderElement>();
        _builderObject = new();
        _SplashShowing = false;

    }

    private bool _SplashShowing;

    private readonly IRepository<GameRound>? _roundsRepo;
    private readonly IRepository<GamePoint> _pointsRepo;
    private readonly IMethodSharingService<Participant> _sharingService;
    private readonly ICombinedRepository _combined;
    private readonly IObjectMessageService _objectMessage;
    private readonly ISplashService _splashService;
    private readonly AppShellViewModel _appShell;
    private ObservableCollection<RoundBuilderGroup> _GameRoundList = new();
    private ObservableCollection<Participant> _ParticipantList = new();
    private ObservableCollection<RoundBuilderElement> _roundElements;
    private Collection<PlayerColumn> _playerColumns;
    private RoundBuilderElement _builderObject;

    public void TriggerRebuild()
    {
        // Trigga eventet
        RebuildRequested?.Invoke(this, EventArgs.Empty);
    }

    // Översta raden
    public ObservableCollection<RoundBuilderElement> RoundElements
    {
        get { return _roundElements; }
        set
        {
            _roundElements = value;
            RaisePropertyChanged(nameof(RoundElements));
        }
    }

    // Nedersta strukturen
    public Collection<PlayerColumn> PlayerColumns
    {
        get { return _playerColumns; }
        set
        {
            _playerColumns = value;
            RaisePropertyChanged(nameof(PlayerColumns));
        }
    }

    public RoundBuilderElement BuilderObject
    {
        get { return _builderObject; }
        set
        {
            _builderObject = value;
            RaisePropertyChanged(nameof(BuilderObject));
        }
    }

    private bool _gobackVisible = true;

    public bool GobackVisible
    {
        get { return _gobackVisible; }
        set
        {
            _gobackVisible = value;
            RaisePropertyChanged(nameof(GobackVisible));
        }
    }




    public ObservableCollection<RoundBuilderElement> Get()
    {

        //_overlay.ShowSplash("Laddar...", 30);

        if (_objectMessage.CurrentGroup != null)
        {
            GobackVisible = _objectMessage.Delivered;
            _objectMessage.Delivered = false;
            //CurrentGroup är satt från RoundStarting ViewModel
            Debug.WriteLine($"Chosen round: {_objectMessage.CurrentGroup.GameRoundId}");
            if (RoundElements.Count > 0)
            {
                RoundElements.Clear();
            }
            foreach (var item in _objectMessage.CurrentGroup.Elements)
            {
                RoundElements.Add(item);
            }

            // Räkna ut vem som är nästa spelare
            var nxt = nextPlayerElement();

            // Aktuell spelare sätts som BuilderObject
            BuilderObject.ParticipantName = _objectMessage.CurrentGroup.Elements[nxt].ParticipantName;
            BuilderObject.GameRoundId = _objectMessage.CurrentGroup.GameRoundId;
            BuilderObject.ParticipantId = _objectMessage.CurrentGroup.Elements[nxt].ParticipantId;
            BuilderObject.Status = _objectMessage.CurrentGroup.Status;

            // Alla poängposter från samtliga spelare i rundan samlas ihop och fördelas per deltagare
            var localElements = _combined.roundBuilderElementsTotalById(_objectMessage.CurrentGroup.GameRoundId);

            FillupResultTable(localElements);

            foreach (var col in _playerColumns)
            {
                RoundElements.FirstOrDefault(e => e.ParticipantId == col.PlayerId).GameRegPoints = col.PlayerPoints;
            }
            TriggerRebuild();
        }
        return RoundElements;
    }


    public void StoreAndHandlePoints()
    {
        var game = _roundsRepo.Get(BuilderObject.GameRoundId).GetAwaiter().GetResult();
        var regNr = RoundElements.Count > 0 ? RoundElements.Max(e => e.GameRoundRegNr) + 1 : 1;

        if (game.GameStatus == GamePointStatus.New)
        {
            game.GameStatus = GamePointStatus.InProgress;
            regNr = regNr == 0 ? 1 : regNr;
            _roundsRepo.Save(game);

        }

        BuilderObject.Status = game.GameStatus;
        var points = BuilderObject.GameRegPoints;
        var newPoint = new GamePoint
        {
            ParticipantId = BuilderObject.ParticipantId,
            GameRoundId = BuilderObject.GameRoundId,
            GameDate = DateTime.Now,
            GameRoundRegNr = regNr,
            GameRegPoints = points
        };
        var pointId = _pointsRepo?.Save(newPoint).GetAwaiter().GetResult();

        // Uppdatera listan med element
        var tmpElements = _combined.roundBuilderElementsDbById(BuilderObject.GameRoundId);
        RoundElements.Clear();
        foreach (var item in tmpElements)
        {
            item.Status = GamePointStatus.InProgress;
            RoundElements.Add(item);
        }

        // Uppdatera spelaren som skall spela nästa
        var nxt = nextPlayerElement();
        BuilderObject.GameRegPoints = 0;
        BuilderObject.ParticipantName = RoundElements[nxt].ParticipantName;
        BuilderObject.ParticipantId = RoundElements[nxt].ParticipantId;
        BuilderObject.GameRoundId = RoundElements[0].GameRoundId;

        var localElements = _combined.roundBuilderElementsTotalById(BuilderObject.GameRoundId);
        FillupResultTable(localElements);
        foreach (var col in _playerColumns)
        {
            RoundElements.FirstOrDefault(e => e.ParticipantId == col.PlayerId).GameRegPoints = col.PlayerPoints;
        }
        TriggerRebuild();
    }

    private int nextPlayerElement()
    {
        for (int i = 0; i < RoundElements.Count; i++)
        {
            if (RoundElements[i].GameRoundRegNr == -1 ||
               (i > 0 && (RoundElements[i - 1].GameRoundRegNr > RoundElements[i].GameRoundRegNr)) ||
                   (i == 0 && RoundElements[i].GameRoundRegNr < RoundElements[RoundElements.Count - 1].GameRoundRegNr))
                return i;
        }
        return -1;
    }

    private void FillupResultTable(IEnumerable<RoundBuilderElement> elements)
    {
        if (_playerColumns != null)
        {
            _playerColumns.Clear();
        }
        else
        {
            _playerColumns = new Collection<PlayerColumn>();
        }

        //        if (elements.Any(g => g.GameRegPoints > 0))
        if (BuilderObject.Status == GamePointStatus.InProgress)
        {
            PlayerColumn player = new PlayerColumn();

            foreach (var element in elements)
            {
                player = _playerColumns.FirstOrDefault(p => p.PlayerId == element.ParticipantId);

                if (player == null)
                {
                    player = new PlayerColumn
                    {
                        PlayerName = element.ParticipantName,
                        PlayerId = element.ParticipantId,
                        PlayerPoints = 0
                    };
                }

                if (element.GameRegPoints > 0)
                {
                    player.Values.Add(element.GameRegPoints.ToString());
                    player.PlayerPoints += element.GameRegPoints;
                    if (player.PlayerPoints > 10000)
                    {
                        var winner = RoundElements.FirstOrDefault(e => e.ParticipantId == player.PlayerId);
                        winner.Status = GamePointStatus.Winning;
                    }
                }
                //oldPart = element.ParticipantId;

                if (!_playerColumns.Contains(player))
                {
                    _playerColumns.Add(player);
                }
            }
        }
        else
        {
            Random slumper = new Random();

            foreach (var element in elements)
            {
                var player = new PlayerColumn
                {
                    PlayerName = element.ParticipantName,
                    PlayerId = element.ParticipantId,
                    PlayerPoints = 0
                };

                for (int i = 0; i < slumper.Next(6); i++)
                {
                    player.Values.Add(slumper.Next(1, 10).ToString());
                }

                _playerColumns.Add(player);
            }
        }
    }

    public async void ToggleSplash()
    {

        if (!_SplashShowing)
        {
            //_overlay.ShowSplash("Clcicked!", 5000);
            await _splashService.ShowSplash("Clicked", 0);
            _SplashShowing = true;
        }
        else
        {
            await _splashService.HideAsync();
            _SplashShowing = false;
        }

    }

    public void GobackAsync()
    {
        _appShell.RoundRunningVisible = true;
    }
}


