package org.mafagafogigante.dungeon.game;

import org.mafagafogigante.dungeon.logging.DungeonLogger;

import com.eclipsesource.json.JsonObject;
import com.eclipsesource.json.JsonValue;
import org.jetbrains.annotations.NotNull;

/**
 * A factory of names. Names should be created through this factory.
 */
public final class NameFactory {

  private NameFactory() {
    throw new AssertionError();
  }

  /**
   * Creates a new name from a singular form.
   */
  public static Name newInstance(@NotNull String singular) {
    return newInstance(singular, singular + 's');
  }

  /**
   * Creates a new name from a singular and a plural form.
   */
  private static Name newInstance(String singular, String plural) {
    return new BaseName(singular, plural);
  }

  /**
   * Creates the name the corpse item of a creature whose name is provided should have.
   */
  public static Name newCorpseName(Name creatureName) {
    return newInstance(creatureName.getSingular() + " Corpse");
  }

  /**
   * Attempts to generate a name object from a JSON object.
   *
   * <p>The JSON object should have the form:
   * <pre>
   *   {"singular": "singularForm", "plural": "pluralForm"}
   * </pre>
   *
   *
   * <p>If the plural form is obtained by appending 's' to the singular form, the plural form should be omitted.
   * Becoming simply:
   * <pre>
   *   {"singular": "singularForm"}
   * </pre>
   * This rule helps remove unnecessary information from developers reading the resource files.
   */
  public static Name fromJsonObject(@NotNull JsonObject jsonObject) {
    String singular = jsonObject.get("singular").asString();
    String plural = readOrRenderPlural(jsonObject, singular);
    return newInstance(singular, plural);
  }

  /**
   * Reads the value for "plural", if present, or generates the plural value by appending 's' to the singular form.
   *
   * <p>If the plural form is present and happens to be identical to what would be generated by appending 's' to the
   * singular form, a warning is logged about unnecessary data.
   */
  private static String readOrRenderPlural(@NotNull JsonObject jsonObject, String singular) {
    JsonValue value = jsonObject.get("plural");
    if (value == null) {
      return singular + 's';
    } else {
      String plural = value.asString();
      warnIfPluralIsUnnecessary(singular, plural);
      return plural;
    }
  }

  private static void warnIfPluralIsUnnecessary(@NotNull String singular, @NotNull String plural) {
    if ((singular + 's').equals(plural)) {
      DungeonLogger.warning("Unnecessary JSON property: " + plural + " can be rendered from " + singular + ".");
    }
  }

}
