import PlaceableFilter from "./placeable-filter.mjs";

/**
 * @import {ContextMenuCallback} from "../../ux/context-menu.mjs";
 */

/**
 * An advanced filter dialog for the AmbientLight placeable tab.
 * @extends {PlaceableFilter}
 */
export default class AmbientLightFilter extends PlaceableFilter {
  /** @override */
  static DEFAULT_OPTIONS = {
    id: "ambient-light-filter"
  };

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

  /** @override */
  static PARTS = {
    body: {
      root: true,
      classes: ["standard-form"],
      template: "templates/sidebar/filters/ambient-light.hbs"
    }
  };

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

  /** @inheritDoc */
  async _prepareContext(options) {
    const context = await super._prepareContext(options);
    const { StringField, BooleanField } = foundry.data.fields;
    const { animationType, color, negative, walls, vision } = this.tab._filterState;

    // Build animation type choices from the registered animation types.
    const animationChoices = {
      "": "LIGHT.FIELDS.animation.type.any",
      none: "LIGHT.FIELDS.animation.type.none"
    };
    for ( const [k, v] of foundry.utils.objectEntries(CONFIG.Canvas.lightAnimations) ) animationChoices[k] = v.label;
    context.animationType = {
      field: new StringField({
        choices: animationChoices, label: "LIGHT.FIELDS.animation.type.label"
      }, { name: "animation.type" }),
      value: animationType ?? ""
    };
    context.color = { value: color };
    context.negative = {
      field: new BooleanField({ label: "LIGHT.FIELDS.negative.label" }, { name: "negative" }),
      value: negative
    };
    context.walls = {
      field: new BooleanField({ label: "AMBIENT_LIGHT.FIELDS.walls.label" }, { name: "walls" }),
      value: walls
    };
    context.vision = {
      field: new BooleanField({ label: "AMBIENT_LIGHT.FIELDS.vision.label" }, { name: "vision" }),
      value: vision
    };
    return context;
  }

  /* -------------------------------------------- */
  /*  Event Listeners & Handlers                  */
  /* -------------------------------------------- */

  /** @inheritDoc */
  _attachFrameListeners() {
    super._attachFrameListeners();
    new foundry.applications.ux.ContextMenu.implementation(
      this.element, "[data-action='selectColor']", [], {
        eventName: "click",
        fixed: true,
        relative: "target",
        jQuery: false,
        onOpen: () => { ui.context.menuItems = this.#buildColorMenuItems(); }
      }
    );
  }

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

  /**
   * Build the menu items for the color filter context menu.
   * @returns {ContextMenuEntry[]}
   */
  #buildColorMenuItems() {
    const state = this.tab._filterState;

    // Collect unique colours in use across all scene lights, sorted alphabetically.
    const colors = new Set();
    for ( const light of canvas.scene?.lights ?? [] ) {
      if ( light.config.color ) colors.add(light.config.color.css);
    }

    /**
     * Generate color filter callback.
     * @param {string|null} color  The filtered color.
     * @returns {ContextMenuCallback}
     */
    const onFilterColor = color => () => {
      state.color = color;
      this.tab._applyFilters();
      this.render();
    };

    return [
      {
        label: "LIGHT.FIELDS.animation.type.any",
        onClick: onFilterColor(null)
      },
      ...Array.from(colors).sort().map(color => ({
        label: color,
        icon: `<i class="color-swatch" style="background: ${color};"></i>`,
        onClick: onFilterColor(color)
      }))
    ];
  }

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

  /** @inheritDoc */
  _onChangeForm(formConfig, event) {
    const { target } = event;
    const state = this.tab._filterState;
    switch ( target.name ) {
      case "animation.type":
        state.animationType = target.value || null;
        break;
      case "negative": state.negative = target.checked; break;
      case "walls": state.walls = target.checked; break;
      case "vision": state.vision = target.checked; break;
      default: return;
    }
    this.tab._applyFilters();
  }
}
