import TypeDataModel from "../abstract/type-data.mjs";
import * as fields from "./fields.mjs";

/**
 * @import ActiveEffect from "../documents/active-effect.mjs";
 * @import {EffectChangeData} from "../documents/_types.mjs";
 */

/**
 * A TypeDataModel for {@link ActiveEffect}s. A single ArrayField is defined for {@link EffectChangeData}. A system can
 * override the changes SchemaField but must preserve definitions for type, phase, and priority.
 */
export default class ActiveEffectTypeDataModel extends TypeDataModel {
  /** @override */
  static defineSchema() {
    return {
      changes: new fields.ArrayField(new fields.SchemaField({
        key: new fields.StringField({required: true}),
        type: new fields.StringField({required: true, blank: false, initial: "add",
          validate: ActiveEffectTypeDataModel.#validateType}),
        value: new fields.AnyField({required: true, nullable: true, serializable: true, initial: ""}),
        phase: new fields.StringField({required: true, blank: false, initial: "initial"}),
        priority: new fields.NumberField()
      }))
    };
  }

  /* -------------------------------------------- */

  /**
   * Validate that an {@link EffectChangeData#type} string is well-formed.
   * @param {string} type The string to be validated
   * @returns {true}
   * @throws {Error} An error if the type string is malformed
   */
  static #validateType(type) {
    if ( type.length < 3 ) throw new Error("must be at least three characters long");
    if ( !/^custom\.-?\d+$/.test(type) && !type.split(".").every(s => /^[a-z0-9]+$/i.test(s)) ) {
      throw new Error(
        "A change type must either be a sequence of dot-delimited, alpha-numeric substrings or of the form"
                + ' "custom.{number}"'
      );
    }
    return true;
  }
}
