import { consume } from "@lit/context";
import { mdiCheck } from "@mdi/js";
import type { CSSResultGroup } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { styleMap } from "lit/directives/style-map";
import { consumeLocalize } from "../../../common/decorators/consume-context-entry";
import { stateColorCss } from "../../../common/entity/state_color";
import { supportsFeature } from "../../../common/entity/supports-feature";
import type { LocalizeFunc } from "../../../common/translations/localize";
import "../../../components/ha-control-button";
import "../../../components/ha-control-button-group";
import "../../../components/ha-outlined-icon-button";
import "../../../components/ha-state-icon";
import { apiContext } from "../../../data/context";
import type { LockEntity } from "../../../data/lock";
import {
  LockEntityFeature,
  callProtectedLockService,
  canOpen,
  isJammed,
} from "../../../data/lock";
import "../../../state-control/lock/ha-state-control-lock-toggle";
import type { HomeAssistantApi } from "../../../types";
import "../components/ha-more-info-state-header";
import { moreInfoControlStyle } from "../components/more-info-control-style";

const CONFIRM_TIMEOUT_SECOND = 5;
const DONE_TIMEOUT_SECOND = 2;

type ButtonState = "normal" | "confirm" | "done";

@customElement("more-info-lock")
class MoreInfoLock extends LitElement {
  @state()
  @consume({ context: apiContext, subscribe: true })
  private _api!: HomeAssistantApi;

  @state()
  @consumeLocalize()
  private _localize!: LocalizeFunc;

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

  @state() public _buttonState: ButtonState = "normal";

  private _buttonTimeout?: number;

  private _setButtonState(buttonState: ButtonState, timeoutSecond?: number) {
    clearTimeout(this._buttonTimeout);
    this._buttonState = buttonState;
    if (timeoutSecond) {
      this._buttonTimeout = window.setTimeout(() => {
        this._buttonState = "normal";
      }, timeoutSecond * 1000);
    }
  }

  private async _open() {
    if (this._buttonState !== "confirm") {
      this._setButtonState("confirm", CONFIRM_TIMEOUT_SECOND);
      return;
    }

    callProtectedLockService(
      this,
      {
        callService: this._api.callService,
        callWS: this._api.callWS,
        localize: this._localize,
      },
      this.stateObj!,
      "open"
    );

    this._setButtonState("done", DONE_TIMEOUT_SECOND);
  }

  private _resetButtonState() {
    this._setButtonState("normal");
  }

  disconnectedCallback(): void {
    super.disconnectedCallback();
    this._resetButtonState();
  }

  private async _lock() {
    callProtectedLockService(
      this,
      {
        callService: this._api.callService,
        callWS: this._api.callWS,
        localize: this._localize,
      },
      this.stateObj!,
      "lock"
    );
  }

  private async _unlock() {
    callProtectedLockService(
      this,
      {
        callService: this._api.callService,
        callWS: this._api.callWS,
        localize: this._localize,
      },
      this.stateObj!,
      "unlock"
    );
  }

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

    const supportsOpen = supportsFeature(this.stateObj, LockEntityFeature.OPEN);

    const color = stateColorCss(this.stateObj);
    const style = {
      "--state-color": color,
    };

    return html`
      <ha-more-info-state-header
        .stateObj=${this.stateObj}
      ></ha-more-info-state-header>
      <div class="controls" style=${styleMap(style)}>
        ${
          isJammed(this.stateObj)
            ? html`
                <div class="status">
                  <span></span>
                  <div class="icon">
                    <ha-state-icon .stateObj=${this.stateObj}></ha-state-icon>
                  </div>
                </div>
              `
            : html`
                <ha-state-control-lock-toggle
                  @lock-service-called=${this._resetButtonState}
                  .stateObj=${this.stateObj}
                >
                </ha-state-control-lock-toggle>
              `
        }
        ${
          supportsOpen
            ? html`
                <div class="buttons">
                  ${
                    this._buttonState === "done"
                      ? html`
                          <p class="open-done">
                            <ha-svg-icon path=${mdiCheck}></ha-svg-icon>
                            ${this._localize("ui.card.lock.open_door_done")}
                          </p>
                        `
                      : html`
                          <ha-control-button
                            .disabled=${!canOpen(this.stateObj)}
                            class="open-button ${this._buttonState}"
                            @click=${this._open}
                          >
                            ${
                              this._buttonState === "confirm"
                                ? this._localize(
                                    "ui.card.lock.open_door_confirm"
                                  )
                                : this._localize("ui.card.lock.open_door")
                            }
                          </ha-control-button>
                        `
                  }
                </div>
              `
            : nothing
        }
      </div>
      <div>
        ${
          isJammed(this.stateObj)
            ? html`
                <ha-control-button-group class="jammed">
                  <ha-control-button @click=${this._unlock}>
                    ${this._localize("ui.card.lock.unlock")}
                  </ha-control-button>
                  <ha-control-button @click=${this._lock}>
                    ${this._localize("ui.card.lock.lock")}
                  </ha-control-button>
                </ha-control-button-group>
              `
            : nothing
        }
      </div>
    `;
  }

  static get styles(): CSSResultGroup {
    return [
      moreInfoControlStyle,
      css`
        ha-control-button {
          font-size: var(--ha-font-size-m);
          height: 60px;
          --control-button-border-radius: var(--ha-border-radius-3xl);
        }
        .open-button {
          width: 130px;
          --control-button-background-color: var(--state-color);
        }
        .open-button.confirm {
          --control-button-background-color: var(--warning-color);
        }
        .open-done {
          line-height: 60px;
          display: flex;
          align-items: center;
          flex-direction: row;
          gap: var(--ha-space-2);
          font-weight: var(--ha-font-weight-medium);
          color: var(--success-color);
        }
        ha-control-button-group.jammed {
          --control-button-group-thickness: 60px;
          width: 100%;
          max-width: 400px;
          margin: 0 auto;
        }
        @keyframes pulse {
          0% {
            opacity: 1;
          }
          50% {
            opacity: 0;
          }
          100% {
            opacity: 1;
          }
        }
        .status {
          display: flex;
          align-items: center;
          flex-direction: column;
          justify-content: center;
          height: 45vh;
          max-height: 320px;
          min-height: 200px;
        }
        .status .icon {
          position: relative;
          --mdc-icon-size: 80px;
          animation: pulse 1s infinite;
          color: var(--state-color);
          border-radius: var(--ha-border-radius-circle);
          width: 144px;
          height: 144px;
          display: flex;
          align-items: center;
          justify-content: center;
        }
        .status .icon::before {
          content: "";
          position: absolute;
          top: 0;
          left: 0;
          height: 100%;
          width: 100%;
          border-radius: var(--ha-border-radius-circle);
          background-color: var(--state-color);
          transition: background-color 180ms ease-in-out;
          opacity: 0.2;
        }
      `,
    ];
  }
}

declare global {
  interface HTMLElementTagNameMap {
    "more-info-lock": MoreInfoLock;
  }
}
