using Model.Stub;
using System.Security.Cryptography;
using System.Xml.Serialization;

namespace Model;

public class Playlist
{
    public string Name
    {
        get => name;

        set
        {
            if (value != null && value.Length < Manager.MAX_NAME_LENGTH)
            {
                name = value;
            }
        }
    }

    private string name = Manager.DEFAULT_NAME;

    public string Description
    {
        get => description;

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

    private string description = Manager.DEFAULT_DESC;

    public IEnumerable<Title> Titles
    {
        get
        {
            return titles;
        }
    }

    private readonly List<Title> titles = new List<Title>();

    public string ImageURL
    {
        get => imageURL;

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

    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 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 && ImageURL == playlist.ImageURL) 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;
    }
}
