import { consume, type ContextType } from "@lit/context";
import {
  mdiBrightness6,
  mdiCreation,
  mdiFileWordBox,
  mdiLightbulbOff,
  mdiLightbulbOn,
  mdiPower,
} from "@mdi/js";
import type { CSSResultGroup, PropertyValues } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { consumeLocalize } from "../../../common/decorators/consume-context-entry";
import { supportsFeature } from "../../../common/entity/supports-feature";
import type { LocalizeFunc } from "../../../common/translations/localize";
import "../../../components/ha-attribute-icon";
import "../../../components/ha-control-select-menu";
import "../../../components/ha-icon-button-group";
import "../../../components/ha-icon-button-toggle";
import "../../../components/ha-list-item";
import { UNAVAILABLE } from "../../../data/entity/entity";
import {
  shouldShowFavoriteOptions,
  type ExtEntityRegistryEntry,
} from "../../../data/entity/entity_registry";
import { forwardHaptic } from "../../../data/haptics";
import type { LightEntity } from "../../../data/light";
import {
  LightColorMode,
  LightEntityFeature,
  lightSupportsBrightness,
  lightSupportsColor,
  lightSupportsColorMode,
  lightSupportsFavoriteColors,
} from "../../../data/light";
import "../../../state-control/ha-state-control-toggle";
import "../../../state-control/light/ha-state-control-light-brightness";
import { apiContext, formattersContext } from "../../../data/context";
import "../components/ha-more-info-control-select-container";
import "../components/ha-more-info-state-header";
import "../components/lights/ha-favorite-color-button";
import "../components/lights/ha-more-info-light-favorite-colors";
import "../components/lights/light-color-rgb-picker";
import "../components/lights/light-color-temp-picker";
import { moreInfoControlStyle } from "../components/more-info-control-style";
import type { HaDropdownSelectEvent } from "../../../components/ha-dropdown";

type MainControl = "brightness" | "color_temp" | "color";

@customElement("more-info-light")
class MoreInfoLight extends LitElement {
  @state()
  @consumeLocalize()
  private _localize!: LocalizeFunc;

  @state()
  @consume({ context: formattersContext, subscribe: true })
  private _formatters!: ContextType<typeof formattersContext>;

  @state()
  @consume({ context: apiContext, subscribe: true })
  private _api!: ContextType<typeof apiContext>;

  @property({ attribute: false }) public stateObj?: LightEntity;

  @property({ attribute: false }) public entry?: ExtEntityRegistryEntry | null;

  @property({ attribute: false }) public editMode?: boolean;

  @state() private _effect?: string;

  @state() private _mainControl: MainControl = "brightness";

  private _renderEffectIcon = (value: string) =>
    html`<ha-attribute-icon
      .stateObj=${this.stateObj}
      attribute="effect"
      .attributeValue=${value}
    ></ha-attribute-icon>`;

  protected updated(changedProps: PropertyValues<this>): void {
    if (changedProps.has("stateObj")) {
      this._effect = this.stateObj?.attributes.effect;
    }
  }

  private _setMainControl(ev: any) {
    ev.stopPropagation();
    this._mainControl = ev.currentTarget.control;
  }

  private _resetMainControl(ev: any) {
    ev.stopPropagation();
    this._mainControl = "brightness";
  }

  private get _stateOverride() {
    if (this.stateObj?.attributes.brightness) {
      return this._formatters.formatEntityAttributeValue(
        this.stateObj!,
        "brightness"
      );
    }
    return undefined;
  }

  protected render() {
    if (!this.stateObj) {
      return nothing;
    }

    const supportsColorTemp = lightSupportsColorMode(
      this.stateObj,
      LightColorMode.COLOR_TEMP
    );

    const supportsColor = lightSupportsColor(this.stateObj);

    const supportsBrightness = lightSupportsBrightness(this.stateObj);

    const supportsWhite = lightSupportsColorMode(
      this.stateObj,
      LightColorMode.WHITE
    );

    const supportsEffects = supportsFeature(
      this.stateObj,
      LightEntityFeature.EFFECT
    );

    const showFavoriteColors = Boolean(
      this.entry &&
      (this.editMode ||
        (lightSupportsFavoriteColors(this.stateObj) &&
          shouldShowFavoriteOptions(
            this.entry.options?.light?.favorite_colors
          )))
    );

    return html`
      <ha-more-info-state-header
        .stateObj=${this.stateObj}
        .stateOverride=${this._stateOverride}
      ></ha-more-info-state-header>
      <div class="controls">
        ${!supportsBrightness
          ? html`
              <ha-state-control-toggle
                .stateObj=${this.stateObj}
                .iconPathOn=${mdiLightbulbOn}
                .iconPathOff=${mdiLightbulbOff}
              ></ha-state-control-toggle>
            `
          : nothing}
        ${supportsColorTemp || supportsColor || supportsBrightness
          ? html`
              ${supportsBrightness && this._mainControl === "brightness"
                ? html`
                    <ha-state-control-light-brightness
                      .stateObj=${this.stateObj}
                    >
                    </ha-state-control-light-brightness>
                  `
                : nothing}
              ${supportsColor && this._mainControl === "color"
                ? html`
                    <light-color-rgb-picker .stateObj=${this.stateObj}>
                    </light-color-rgb-picker>
                  `
                : nothing}
              ${supportsColorTemp && this._mainControl === "color_temp"
                ? html`
                    <light-color-temp-picker .stateObj=${this.stateObj}>
                    </light-color-temp-picker>
                  `
                : nothing}
              <ha-icon-button-group>
                ${supportsBrightness
                  ? html`
                      <ha-icon-button
                        .disabled=${this.stateObj!.state === UNAVAILABLE}
                        .label=${this._localize(
                          "ui.dialogs.more_info_control.light.toggle"
                        )}
                        @click=${this._toggle}
                      >
                        <ha-svg-icon .path=${mdiPower}></ha-svg-icon>
                      </ha-icon-button>
                    `
                  : nothing}
                ${supportsColor || supportsColorTemp
                  ? html`
                      <div class="separator"></div>
                      <ha-icon-button-toggle
                        .selected=${this._mainControl === "brightness"}
                        .disabled=${this.stateObj!.state === UNAVAILABLE}
                        .label=${this._formatters.formatEntityAttributeName(
                          this.stateObj,
                          "brightness"
                        )}
                        .control=${"brightness"}
                        @click=${this._setMainControl}
                      >
                        <ha-svg-icon .path=${mdiBrightness6}></ha-svg-icon>
                      </ha-icon-button-toggle>
                    `
                  : nothing}
                ${supportsColor
                  ? html`
                      <ha-icon-button-toggle
                        border-only
                        .selected=${this._mainControl === "color"}
                        .disabled=${this.stateObj!.state === UNAVAILABLE}
                        .label=${this._localize(
                          "ui.dialogs.more_info_control.light.color"
                        )}
                        .control=${"color"}
                        @click=${this._setMainControl}
                      >
                        <span class="wheel color"></span>
                      </ha-icon-button-toggle>
                    `
                  : nothing}
                ${supportsColorTemp
                  ? html`
                      <ha-icon-button-toggle
                        border-only
                        .selected=${this._mainControl === "color_temp"}
                        .disabled=${this.stateObj!.state === UNAVAILABLE}
                        .label=${this._localize(
                          "ui.dialogs.more_info_control.light.color_temp"
                        )}
                        .control=${"color_temp"}
                        @click=${this._setMainControl}
                      >
                        <span class="wheel color-temp"></span>
                      </ha-icon-button-toggle>
                    `
                  : nothing}
                ${supportsWhite
                  ? html`
                      <div class="separator"></div>
                      <ha-icon-button
                        .disabled=${this.stateObj!.state === UNAVAILABLE}
                        .label=${this._localize(
                          "ui.dialogs.more_info_control.light.set_white"
                        )}
                        @click=${this._setWhite}
                      >
                        <ha-svg-icon .path=${mdiFileWordBox}></ha-svg-icon>
                      </ha-icon-button>
                    `
                  : nothing}
              </ha-icon-button-group>
              ${showFavoriteColors
                ? html`
                    <ha-more-info-light-favorite-colors
                      .stateObj=${this.stateObj}
                      .entry=${this.entry}
                      .editMode=${this.editMode}
                      @favorite-color-edit-started=${this._resetMainControl}
                    >
                    </ha-more-info-light-favorite-colors>
                  `
                : nothing}
            `
          : nothing}
      </div>
      <div>
        <ha-more-info-control-select-container>
          ${supportsEffects && this.stateObj.attributes.effect_list
            ? html`
                <ha-control-select-menu
                  .label=${this._formatters.formatEntityAttributeName(
                    this.stateObj,
                    "effect"
                  )}
                  .value=${this.stateObj.attributes.effect}
                  .disabled=${this.stateObj.state === UNAVAILABLE}
                  @wa-select=${this._handleEffect}
                  .options=${this.stateObj.attributes.effect_list.map(
                    (effect) => ({
                      value: effect,
                      label: this.stateObj
                        ? this._formatters.formatEntityAttributeValue(
                            this.stateObj,
                            "effect",
                            effect
                          )
                        : effect,
                    })
                  )}
                  .renderIcon=${this._renderEffectIcon}
                >
                  <ha-svg-icon slot="icon" .path=${mdiCreation}></ha-svg-icon>
                </ha-control-select-menu>
              `
            : nothing}
        </ha-more-info-control-select-container>
      </div>
    `;
  }

  private _toggle = () => {
    const service = this.stateObj?.state === "on" ? "turn_off" : "turn_on";
    forwardHaptic(this, "light");
    this._api.callService("light", service, {
      entity_id: this.stateObj!.entity_id,
    });
  };

  private _setWhite = () => {
    this._api.callService("light", "turn_on", {
      entity_id: this.stateObj!.entity_id,
      white: true,
    });
  };

  private _handleEffect(ev: HaDropdownSelectEvent) {
    const newVal = ev.detail.item.value;
    const oldVal = this._effect;

    if (!newVal || oldVal === newVal) return;

    this._api.callService("light", "turn_on", {
      entity_id: this.stateObj!.entity_id,
      effect: newVal,
    });
  }

  static get styles(): CSSResultGroup {
    return [
      moreInfoControlStyle,
      css`
        .button-bar {
          display: flex;
          flex-direction: row;
          align-items: center;
          height: 48px;
          border-radius: var(--ha-border-radius-3xl);
          background-color: rgba(139, 145, 151, 0.1);
          box-sizing: border-box;
          width: auto;
        }
        .wheel {
          width: 30px;
          height: 30px;
          flex: none;
          border-radius: var(--ha-border-radius-xl);
        }
        .wheel.color {
          background-image: url("/static/images/color_wheel.png");
          background-size: cover;
        }
        .wheel.color-temp {
          background: linear-gradient(
            0,
            rgb(166, 209, 255) 0%,
            white 50%,
            rgb(255, 160, 0) 100%
          );
        }
        *[disabled] .wheel {
          filter: grayscale(1) opacity(0.5);
        }
        .buttons {
          flex-wrap: wrap;
          max-width: 250px;
        }
      `,
    ];
  }
}

declare global {
  interface HTMLElementTagNameMap {
    "more-info-light": MoreInfoLight;
  }
}
