// ReSharper disable All
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using QwirkleClassLibrary.Tiles;

namespace QwirkleClassLibrary.Boards;

[DataContract]
public class Cell : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

    [DataMember]
    private readonly int x;

    [DataMember]
    private readonly int y;

    [DataMember]
    public Tile? Tile { get; private set;}

    /// <summary>
    /// This is the constructor for a Cell.
    /// </summary>
    /// <param name="x">The x attribute of the cell.</param>
    /// <param name="y">The y attribute of the cell.</param>
    /// <exception cref="ArgumentException">Throw an exception if the x or y attribute is negative.</exception>
    public Cell(int x, int y)
    {
        if (x < 0 || y < 0)
        {
            throw new ArgumentException(x.ToString() + y.ToString());
        }

        this.x = x;
        this.y = y;
    }

    /// <summary>
    /// A getter for the position of the cell on the x-axis.
    /// </summary>
    /// <returns>The position of the cell on the x-axis.</returns>
    public int GetX
    {
        get { return x; }
    }

    /// <summary>
    /// A getter for the position of the cell on the y-axis.
    /// </summary>
    /// <returns>The position of the cell on the y-axis.</returns>
    public int GetY
    {
        get { return y; }
    }

    /// <summary>
    /// Check if the Cell whether is empty or contains a tile.
    /// </summary>
    /// <returns>True if the cell is empty, false if the cell contains a tile.</returns>
    public bool IsFree
    {
        get { return Tile! == null!; }
    }


    /// <summary>
    /// A setter for the tile in the cell.
    /// </summary>
    /// <param name="addedTile">The tile the player want to add in the cell.</param>
    /// <returns>True if added succefully (if the cell didn't already contain a tile), false if there already was a tile in this cell.</returns>
    public bool SetTile(Tile addedTile)
    {
        if (Tile! == null!)
        {

            Tile = addedTile;
            OnPropertyChanged(nameof(Tile));
            return true;
        }
        else
        {
            return false;
        }
    }

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