import PlaceablePaletteMixin from "./placeable-palette-mixin.mjs";
import RegionConfig from "../region-config.mjs";
import {DOCUMENT_OWNERSHIP_LEVELS} from "@common/constants.mjs";

/**
 * A dialog that provides bulk operation or default values for newly-created regions.
 * @extends {RegionConfig}
 * @mixes PlaceablePaletteMixin
 */
export default class RegionPalette extends PlaceablePaletteMixin(RegionConfig) {
  /** @override */
  static DEFAULT_OPTIONS = {
    id: "region-palette",
    initialData: {
      name: "regionPalette",
      ownership: { default: DOCUMENT_OWNERSHIP_LEVELS.OWNER }
    }
  };

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

  /**
   * The setting key where default data is saved.
   * @type {string}
   */
  static SETTING_KEY = "regionPalette";

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

  /**
   * The placeable document.
   * @type {string}
   */
  static documentName = "Region";

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

  /** @override */
  static TABS = {};

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

  /** @override */
  static PARTS = {
    body: { template: "templates/scene/palette/region/body.hbs" },
    footer: { template: "templates/generic/form-footer.hbs" }
  };

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

  /** @override */
  static _getDefaultLevelData() {
    return {
      levels: [canvas.level.id],
      elevation: {
        bottom: Number.isFinite(canvas.level.elevation.bottom) ? canvas.level.elevation.bottom : null,
        top: Number.isFinite(canvas.level.elevation.top) ? canvas.level.elevation.top : null
      }
    };
  }

  /* -------------------------------------------- */
  /*  Properties                                  */
  /* -------------------------------------------- */

  /** @override */
  static get schema() {
    const schema = super.schema;
    for ( const f of ["name", "shapes", "behaviors", "locked", "ownership", "flags"] ) {
      delete schema.fields[f];
    }
    // The palette's color field can be null to indicate a random color should be used.
    schema.fields.color = new foundry.data.fields.ColorField({ nullable: true, initial: null });
    return schema;
  }

  /* -------------------------------------------- */
  /*  Rendering                                   */
  /* -------------------------------------------- */

  /** @inheritDoc */
  _applyPreset(formData, options={}) {
    const preset = super._applyPreset(formData, options);
    preset.elevation ??= {};
    foundry.utils.mergeObject(preset.elevation, formData.elevation);
  }

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

  /** @inheritDoc */
  async _prepareContext(options) {
    const context = await super._prepareContext(options);
    context.visibilities = Object.entries(CONST.REGION_VISIBILITY).reduce((arr, [key, value]) => {
      arr.push({value, label: _loc(`REGION.VISIBILITY.${key}.label`)});
      return arr;
    }, []);
    context.restrictionTypes = CONST.EDGE_RESTRICTION_TYPES.reduce((arr, value) => {
      arr.push({value, label: _loc(`REGION.RESTRICTION_TYPES.${value}.label`)});
      return arr;
    }, []).sort((a, b) => a.label.localeCompare(b.label, game.i18n.lang));
    context.color = context.source.color;
    if ( (ui.controls.tool?.creation || (this.isSelect && !this.layer?.controlled.length))
      && !game.settings.get("core", this.constructor.SETTING_KEY).color ) {
      context.color = null;
    }
    return context;
  }

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

  /** @override */
  async _preparePartContext(partId, context, options) {
    context.partId = `${this.id}-${partId}`;
    return context;
  }

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

  /** @inheritDoc */
  async _processSubmitData(event, form, submitData, options) {
    const rawColor = form.elements.color.value || null;
    if ( (event.type === "submit") && event.isTrusted ) {
      // Blank color means no change rather than random color in the context of bulk application.
      if ( !rawColor ) delete submitData.color;
      return super._processSubmitData(event, form, submitData, options);
    }

    this.document.updateSource(submitData, options);
    const settings = this.document.toObject();
    if ( rawColor === null ) settings.color = null;
    await game.settings.set("core", this.constructor.SETTING_KEY, settings);
    ui.controls.render({ parts: ["tools"] });
    await this.render();
    return {};
  }
}
