using Model.Stub;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;

namespace Model;

public class Playlist : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

    public string Name
    {
        get => name;

        set
        {
            if (string.IsNullOrEmpty(value) || value.Length > Manager.MAX_NAME_LENGTH)
            {
                return;
            }
            name = value;
            OnPropertyChanged();
        }
    }

    private string name = Manager.DEFAULT_NAME;

    public string Description
    {
        get => description;

        set
        {
            if (value != null && value.Length < Manager.MAX_DESCRIPTION_LENGTH)
            {
                description = value;
            }
            OnPropertyChanged();
        }
    }

    private string description = Manager.DEFAULT_DESC;

    public ObservableCollection<CustomTitle> Titles
    {
        get
        {
            return titles;
        }
        private set
        {
            titles = value;
            OnPropertyChanged();
        }
    }

    private ObservableCollection<CustomTitle> titles = new ObservableCollection<CustomTitle>();

    public string ImageURL
    {
        get => imageURL;

        set
        {
            if (value == null || !value.Contains('.'))
            {
                value = "none.png";
                imageURL = value;
            }
            else if (value.Contains('.'))
            {
                imageURL = value;
            }
            OnPropertyChanged();
        }
    }

    private string imageURL = Manager.DEFAULT_URL;

    public int Index
    {
        get => index;

        set
        {
            if (value < titles.Count)
            {
                index = value;
            }
            else if(Loop)
            {
                index = 0;
            }
        }
    }

    private int index = 0;

    public bool Shuffle { get; set; } = false;

    public bool Loop { get; set; } = false;

    public bool LoopTitle { get; set; } = false;

    private readonly List<int> played = new List<int>();

    public IEnumerable<int> Played
    {
        get
        {
            return new List<int>(played);
        }
    }

    public bool IsSubMenuVisible
    {
        get => isSubMenuVisible;
        set
        {
            if (isSubMenuVisible != value)
            {
                isSubMenuVisible = value;
            }
            OnPropertyChanged(nameof(IsSubMenuVisible));
        }
    }

    private bool isSubMenuVisible;

    public Playlist(string nom, string description, string imageURL)
    {
        Name = nom;
        Description = description;
        ImageURL = imageURL;
    }

    public Playlist()
    {

    }

    public void AddTitle(CustomTitle morceau)
    {
        titles.Add(morceau);
    }

    public void RemoveTitle(CustomTitle morceau)
    {
        titles.Remove(morceau);
    }

    public void NextTitle()
    {
        if (LoopTitle)
        {
            return;
        }

        if (!Shuffle)
        {
            Index++;
            played.Add(Index);
        }
        else
        {
            Index = RandomGenerator(titles.Count);
            played.Add(Index);
        }
    }

    public void PreviousTitle()
    {
        if (LoopTitle)
        {
            return;
        }

        if(!Shuffle)
        {
            if(Index != 0)
            {
                Index--;
                played.RemoveAt(played.Count - 1);
            }
        }
        else
        {
            if (!played.Any())
            {
                return;
            }
            Index = played[played.Count - 1];
            played.RemoveAt(played.Count - 1);
        }
    }

    public Title? GetCurrentTitle()
    {
        if (Index < titles.Count)
        {
            return titles[Index];
        }
        else
        {
            return null;
        }

    }

    public override bool Equals(object? obj)
    {
        if (obj is null) return false;
        if (obj.GetType() != typeof(Playlist)) return false;
        if (obj is Playlist playlist && Name == playlist.Name) return true;
        else return false;
    }

    public override int GetHashCode()
    {
        return ImageURL.GetHashCode();
    }

    public override string ToString()
    {
        return $"Name : {Name}";
    }

    static int RandomGenerator(int n)
    {
        RandomNumberGenerator rng = RandomNumberGenerator.Create();
        byte[] randomBytes = new byte[4];
        rng.GetBytes(randomBytes);
        int randomNumber = BitConverter.ToInt32(randomBytes, 0);
        return randomNumber % n + 1;
    }
}
