import PlaceableConfig from "./placeable-config.mjs";
import AdaptiveLightingShader from "../../canvas/rendering/shaders/lighting/base-lighting.mjs";
import AmbientLightDocument from "@client/documents/ambient-light.mjs";

/**
 * The Application responsible for configuring a single AmbientLight document within a parent Scene.
 */
export default class AmbientLightConfig extends PlaceableConfig {

  /** @inheritDoc */
  static DEFAULT_OPTIONS = {
    classes: ["ambient-light-config"],
    window: {
      contentClasses: ["standard-form"]
    },
    position: {width: 560},
    form: {
      closeOnSubmit: true
    },
    actions: {
      reset: this.#onReset
    }
  };

  /** @override */
  static PARTS = {
    tabs: {
      template: "templates/generic/tab-navigation.hbs"
    },
    basic: {
      template: "templates/scene/parts/light-basic.hbs"
    },
    animation: {
      template: "templates/scene/parts/light-animation.hbs"
    },
    advanced: {
      template: "templates/scene/parts/light-advanced.hbs"
    },
    footer: {
      template: "templates/generic/form-footer.hbs"
    }
  };

  /** @override */
  static TABS = {
    sheet: {
      tabs: [
        {id: "basic", icon: "fa-solid fa-lightbulb"},
        {id: "animation", icon: "fa-solid fa-play"},
        {id: "advanced", icon: "fa-solid fa-gears"}
      ],
      initial: "basic",
      labelPrefix: "AMBIENT_LIGHT.TABS"
    }
  };

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

  /** @inheritDoc */
  async _onRender(context, options) {
    await super._onRender(context, options);
    this.#toggleReset();
  }

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

  /** @inheritDoc */
  async _prepareContext(options) {
    const context = await super._prepareContext(options);
    const {document} = context;
    const isDarkness = document.config.negative;
    return Object.assign(context, {
      tabClasses: "top-tabs",
      light: document,
      colorationTechniques: AdaptiveLightingShader.SHADER_TECHNIQUES,
      isDarkness,
      lightAnimations: isDarkness ? CONFIG.Canvas.darknessAnimations : CONFIG.Canvas.lightAnimations,
      buttons: [
        {
          type: "reset",
          action: "reset",
          icon: "fa-solid fa-arrow-rotate-left",
          label: "AMBIENT_LIGHT.ACTIONS.RESET"
        },
        {
          type: "submit",
          icon: "fa-solid fa-floppy-disk",
          label: `AMBIENT_LIGHT.ACTIONS.${this.document.collection?.has(this.document.id) ? "UPDATE" : "CREATE"}`
        }
      ]
    });
  }

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

  /**
   * Toggle visibility of the reset button which is only visible on the advanced tab.
   */
  #toggleReset() {
    if ( !("advanced" in this.constructor.PARTS) ) return;
    const reset = this.element.querySelector("button[data-action=reset]");
    reset.classList.toggle("hidden", this.tabGroups.sheet !== "advanced");
  }

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

  /** @inheritDoc */
  changeTab(...args) {
    super.changeTab(...args);
    this.#toggleReset();
  }

  /* -------------------------------------------- */
  /*  Real-Time Preview                           */
  /* -------------------------------------------- */

  /** @inheritDoc */
  _onChangeForm(formConfig, event) {
    super._onChangeForm(formConfig, event);

    // Special handling for darkness state change
    if ( (event.target.name === "config.negative") && ("advanced" in this.constructor.PARTS) ) {
      this.render({parts: ["animation", "advanced"]});
    }
  }

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

  /** @inheritDoc */
  _previewChanges(changes) {
    super._previewChanges(changes);
    if ( !this._preview.rendered ) return;
    const redraw = this._preview.object.controls.shape.type !== this._preview.shape.type;
    this._preview.object.renderFlags.set({redraw});
    this._preview.object.initializeLightSource();
  }

  /* -------------------------------------------- */
  /*  Event Listeners and Handlers                */
  /* -------------------------------------------- */

  /**
   * Process reset button click
   * @param {PointerEvent} event                  The originating button click
   * @this {AmbientLightConfig}
   * @returns {Promise<void>}
   */
  static async #onReset(event) {
    event.preventDefault();
    const defaults = AmbientLightDocument.cleanData();
    const keys = ["vision", "config"];
    const configKeys = ["coloration", "contrast", "attenuation", "luminosity", "saturation", "shadows"];
    for ( const k in defaults ) {
      if ( !keys.includes(k) ) delete defaults[k];
    }
    for ( const k in defaults.config ) {
      if ( !configKeys.includes(k) ) delete defaults.config[k];
    }
    this._previewChanges(defaults);
    await this.render();
  }

  /* -------------------------------------------- */
  /*  Deprecations and Compatibility              */
  /* -------------------------------------------- */

  /**
   * @deprecated since v14
   * @ignore
   */
  get preview() {
    foundry.utils.logCompatibilityWarning("The AmbientLightConfig#preview has been deprecated in favor of AmbientLightConfig#_preview",
      {since: 14, until: 16, once: true});
    return this._preview;
  }
}
