import titleize from 'titleize';
import { actionCards, cardTypes } from '../namespaces/cardTypes.js';

/**
 * UNO card class.
 */
export default class Card {
  /**
   * Creates a new UNO Card.
   * @param {string} color - The color of the card.
   *    Either `red`, `yellow`, `green`, `blue`, or `wild`.
   * @param {string} symbol - The number (in `string`) or symbol of the card.
   *    Check {@link cardTypes} for lists of valid symbols and its name.
   */
  constructor(color, symbol) {
    let Color = color.toLowerCase();
    const Symbol = symbol.toLowerCase();

    // Automatically change the `color` to `wild` if its a wild card.
    if (['w', '+4'].includes(Symbol)) Color = 'wild';
    else if (Color === 'wild') {
      throw new Error(`${cardTypes[Symbol]} Card cannot have \`wild\` color`);
    }

    if (!'red,yellow,green,blue,wild'.split(',').includes(Color)) {
      throw new RangeError(
        'Invalid color value. '
        + 'Must be either `red`, `yellow`. `green`, `blue`, or `wild`',
      );
    }

    /**
     * The color of the card.
     * @type {string}
     */
    this.color = Color;

    /**
     * The number (in `string`) or symbol of the card.
     * @type {string}
     */
    this.symbol = Symbol;

    if (Symbol.length === 1 && !Number.isNaN(parseInt(Symbol, 10))) {
      /**
       * The number of the card. An alias for {@link Symbol}
       *    properties if the card is a number card.
       * @type {number}
       */
      this.number = parseInt(Symbol, 10);
    }

    /**
     * The name of the card.
     * @type {string}
     */
    this.name = titleize(
      `${Color === 'wild' ? '' : Color} ${cardTypes[Symbol]} Card`,
    ).trim();

    // Define the points for each type of cards.
    /**
     * The points of the card.
     * @type {number}
     */
    this.points = 0;
    if (actionCards.includes(Symbol)) {
      if (['w', '+4'].includes(Symbol)) this.points = 50;
      else this.points = 20;
    } else this.points = parseInt(Symbol, 10);
  }

  /**
   * Returns the name of the class.
   * @returns {string}
   */
  static toString() {
    return '<class Card>';
  }

  /**
   * Returns a string representation of UNO Card.
   * @returns {string}
   */
  toString() {
    return this.name;
  }
}