import Document from "../abstract/document.mjs";
import * as fields from "../data/fields.mjs";
import {mergeObject} from "../utils/helpers.mjs";

/**
 * @import {LevelData} from "@common/documents/_types.mjs";
 */

/**
 * The Level Document.
 * Defines the DataSchema and common behaviors for a Level which are shared between both client and server.
 * @extends {Document<LevelData>}
 * @category Documents
 *
 * @example Create Scene Levels
 * ```js
 * await canvas.scene.createEmbeddedDocuments("Level", [
 *   {
 *     name: "Basement",
 *     elevation: {bottom: -10, top: 0},
 *     background: {
 *       src: "worlds/scene-levels-test/assets/cabin/BasementBackground.webp"
 *     },
 *     foreground: {
 *       src: "worlds/scene-levels-test/assets/cabin/BasementForeground.webp"
 *     }
 *   },
 *   {
 *     name: "Downstairs",
 *     elevation: {bottom: 0, top: 10},
 *     background: {
 *       src: "worlds/scene-levels-test/assets/cabin/DownstairsBackground.webp"
 *     },
 *     foreground: {
 *       src: "worlds/scene-levels-test/assets/cabin/DownstairsForeground.webp"
 *     }
 *   },
 *   {
 *     name: "Upstairs",
 *     elevation: {bottom: 10, top: 20},
 *     background: {
 *       src: "worlds/scene-levels-test/assets/cabin/UpstairsBackground.webp"
 *     },
 *     foreground: {
 *       src: "worlds/scene-levels-test/assets/cabin/UpstairsForeground.webp"
 *     }
 *   }
 * ]);
 * ```
 */
export default class BaseLevel extends Document {

  /* ---------------------------------------- */
  /*  Model Configuration                     */
  /* ---------------------------------------- */

  /** @inheritdoc */
  static metadata = Object.freeze(mergeObject(super.metadata, {
    name: "Level",
    collection: "levels",
    label: "DOCUMENT.Level",
    labelPlural: "DOCUMENT.Levels",
    isEmbedded: true,
    schemaVersion: "14.364"
  }, {inplace: false}));

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

  /** @override */
  static LOCALIZATION_PREFIXES = ["DOCUMENT", "SCENE_LEVEL"];

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

  /** @inheritDoc */
  static defineSchema() {
    return {
      _id: new fields.DocumentIdField(),
      name: new fields.StringField({required: true, blank: false, textSearch: true}),
      elevation: new fields.SchemaField({
        bottom: new fields.NumberField({required: true, nullable: true, initial: 0}), // Treat null as -Infinity
        top: new fields.NumberField({required: true, nullable: true, initial: 20}) // Treat null as +Infinity
      }, {
        validate: d => (d.bottom ?? -Infinity) <= (d.top ?? Infinity),
        validationError: "elevation.top may not be less than elevation.bottom"
      }),
      background: new fields.SchemaField({
        color: new fields.ColorField({nullable: false, initial: "#999999"}),
        src: new fields.FilePathField({required: true, categories: ["TEXTURE"], initial: null, virtual: true}),
        tint: new fields.ColorField({required: true, nullable: false, initial: "#ffffff"}),
        alphaThreshold: new fields.AlphaField({nullable: false, initial: 0.75})
      }),
      foreground: new fields.SchemaField({
        src: new fields.FilePathField({required: true, categories: ["TEXTURE"], initial: null, virtual: true}),
        tint: new fields.ColorField({required: true, nullable: false, initial: "#ffffff"}),
        alphaThreshold: new fields.AlphaField({nullable: false, initial: 0.75})
      }),
      fog: new fields.SchemaField({
        src: new fields.FilePathField({required: true, categories: ["TEXTURE"], initial: null, virtual: true})
      }),
      textures: new fields.SchemaField({
        anchorX: new fields.NumberField({required: true, nullable: false, initial: 0.5}),
        anchorY: new fields.NumberField({required: true, nullable: false, initial: 0.5}),
        offsetX: new fields.NumberField({required: true, nullable: false, integer: true, initial: 0}),
        offsetY: new fields.NumberField({required: true, nullable: false, integer: true, initial: 0}),
        fit: new fields.StringField({required: true, initial: "fill", choices: CONST.TEXTURE_DATA_FIT_MODES}),
        scaleX: new fields.NumberField({required: true, nullable: false, initial: 1}),
        scaleY: new fields.NumberField({required: true, nullable: false, initial: 1}),
        rotation: new fields.AngleField({initial: 0})
      }),
      visibility: new fields.SchemaField({
        levels: new fields.SceneLevelsSetField()
      }),
      sort: new fields.IntegerSortField(),
      flags: new fields.DocumentFlagsField()
    };
  }
}
