import { html, css, CSSResultGroup, TemplateResult, nothing, PropertyValues } from 'lit';
import { customElement, property, query } from 'lit/decorators.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { styleMap } from 'lit/directives/style-map.js';

import './vic-btn-card';
import './vic-state-item';
import './vic-btn-badge';
import { hasAction } from '../../../types/actions-config';
import { handleAction } from '../../../types/ha-frontend/panels/common/handle-actions';
import { ActionDomEvent, ActionHandleOpts, addActionHandler } from '../../../utils/lovelace/action-handler';
import { addActions } from '../../../utils/lovelace/tap-action';
import { BaseButton } from '../../base-button';

@customElement('vic-button-card-item')
export class VicButtonCardItem extends BaseButton {
  constructor() {
    super();
  }
  @property({ type: Number, attribute: 'item-index' }) public itemIndex?: number;
  @property({ type: Boolean, reflect: true, attribute: 'dimmed-in-editor' }) public dimmedInEditor = false;

  @query('ha-card') private _haCard!: HTMLElement;

  protected firstUpdated(_changedProperties: PropertyValues): void {
    super.firstUpdated(_changedProperties);
    this._addActions();
  }
  private _addActions(): void {
    if (!Boolean(this._hasAction || this._hasIconAction)) {
      return;
    }
    const clickable = this.shadowRoot?.querySelector('#clickable-background') as HTMLElement;
    const icon = this.shadowRoot?.querySelector('vic-btn-shape-icon') as HTMLElement;

    const handlerOptions: ActionHandleOpts = {
      hasHold: true,
      hasDoubleClick: true,
      hasClick: true,
    };

    if (clickable) {
      addActionHandler(clickable, handlerOptions);
      clickable.addEventListener('action', this._handleCardEvent.bind(this) as EventListener);
    }
    if (icon) {
      // Separate handlers for icon actions
      if (this._hasIconAction) {
        // If icon has its own actions, use those instead of the main handlers
        const iconActionSpec = this._iconActions;
        addActions(icon, iconActionSpec);
      } else {
        addActionHandler(icon, handlerOptions);
        icon.addEventListener('action', this._handleCardEvent.bind(this) as EventListener);
      }
    }
  }

  protected render(): TemplateResult | typeof nothing {
    if (!this._btnConfig || !this._hass) {
      return nothing;
    }
    const isUsingDefault = this._usingDefaultButton;
    const stateObj = this._stateObj;
    const btnShowConfig = this._btnShowConfig;

    const imageUrl = btnShowConfig.icon_type === 'entity-picture' ? this._getImageUrl() : undefined;
    let icon =
      btnShowConfig.icon_type === 'icon-template' ? this._getTemplateValue('icon_template') : this._btnConfig.icon;
    if (isUsingDefault) {
      icon = this._getValueFromDefaultButton('icon')! as string;
    }
    const iconStyle = this._computeIconStyle();

    const badgeVisible = isUsingDefault
      ? this.car._getDefaultButtonNotifyByKey(this.buttonKey as any)
      : Boolean(this._getTemplateValue('notify'));
    const notifyIcon = this._getTemplateValue('notify_icon');
    const notifyText = this._getTemplateValue('notify_text');
    const notifyColor = isUsingDefault ? 'var(--primary-color)' : this._getTemplateValue('notify_color');

    const _hasAction = this._hasAction;
    const _hasIconAction = this._hasIconAction;
    const _btnHasAction = Boolean(_hasAction || _hasIconAction);

    return html`
      <ha-card ?transparent=${btnShowConfig.transparent} style=${styleMap(iconStyle)} ?isUsingDefault=${isUsingDefault}>
        <div
          id="clickable-background"
          class="background"
          role=${ifDefined(_hasAction ? 'button' : undefined)}
          tabindex=${ifDefined(_hasAction ? '0' : undefined)}
        >
          <ha-ripple .disabled=${!_hasAction}></ha-ripple>
        </div>
        <vic-btn-card .btnShowConfig=${btnShowConfig}>
          <vic-state-item
            .btnShowConfig=${btnShowConfig}
            >
            <vic-btn-shape-icon
              slot="icon"
              .interactive=${_hasIconAction}
              .imageSrc=${imageUrl}
              role=${ifDefined(_btnHasAction ? 'button' : undefined)}
              tabindex=${ifDefined(_btnHasAction ? '0' : undefined)}
            >
              <ha-state-icon
                slot="icon"
                .hass=${this._hass}
                .stateObj=${stateObj}
                .icon=${icon}>
              </ha-state-icon>
            </vic-btn-shape-icon>
            ${
              badgeVisible
                ? html`<vic-btn-badge
                    slot="badge"
                    .isText=${Boolean(notifyText)}
                    style=${styleMap({ '--vic-btn-badge-background-color': notifyColor })}
                  >
                    ${notifyText
                      ? html`<span>${notifyText}</span>`
                      : html`<ha-icon .icon=${notifyIcon || 'mdi:alert-circle-outline'}></ha-icon>`}
                  </vic-btn-badge>`
                : nothing
            }
              </vic-btn-badge>

            ${this._renderStateInfo()}
          </vic-state-item>
        </vic-btn-card>
      </ha-card>
    `;
  }

  private _handleCardEvent(ev: ActionDomEvent): void {
    ev.stopPropagation();
    const action = ev.detail.action;
    const isAction = this._btnConfig?.button_type === 'action';
    const config = this._btnActionConfig;
    const _hasAction = hasAction(config[`${action}_action`]);
    switch (action) {
      case 'tap':
        if (!isAction) {
          this.dispatchEvent(new CustomEvent('click-index', { bubbles: true, composed: true }));
          return;
        }
        if (_hasAction) {
          handleAction(this, this.hass, config, action);
        }
        break;
      case 'hold':
      case 'double_tap':
        if (_hasAction) {
          handleAction(this, this.hass, config, action);
        }
        break;
      default:
        break;
    }
  }

  public _toggleHighlight(): void {
    const haCard = this._haCard;
    if (!haCard) {
      return;
    }
    haCard.classList.add('highlight');
    haCard.addEventListener('animationend', () => {
      haCard.classList.remove('highlight');
    });
  }

  public _zoomInEffect(): void {
    const haCard = this.shadowRoot?.querySelector('ha-card') as HTMLElement;
    haCard.style.animationDelay = `${this.itemIndex! * 50}ms`;
    haCard.classList.add('zoom-in');
    haCard.addEventListener(
      'animationend',
      () => {
        haCard.classList.remove('zoom-in');
        haCard.style.removeProperty('animation-delay');
      },
      { once: true }
    );
  }

  static get styles(): CSSResultGroup {
    return [
      super.styles,
      css`
        :host {
          --icon-color: rgba(var(--rgb-primary-text-color), 0.75);
          --icon-color-disabled: rgb(var(--default-disabled-color));
          --icon-size: 36px;
          --icon-symbol-size: 0.667em;
          --icon-border-radius: 50%;
          --shape-icon-opacity: 0.2;
          --shape-hover-opacity: 0.35;
          --shape-color: var(--disabled-text-color);
          --shape-color-disabled: rgba(var(--default-disabled-color), 0.2);
          --shape-outline-color: transparent;
        }
        :host([dimmed-in-editor]) {
          opacity: 0.3;
          filter: blur(1px);
        }
        :host([dimmed-in-editor]:hover) {
          opacity: 1;
          filter: none;
        }

        ha-card {
          --ha-ripple-color: var(--icon-color);
          --ha-ripple-hover-opacity: 0.04;
          --ha-ripple-pressed-opacity: 0.12;
          height: 100%;
          transition: box-shadow 180ms ease-in-out, border-color 180ms ease-in-out;
          padding: 0;
          margin: 0;
          position: relative;
          box-sizing: border-box;
          display: flex;
          flex-direction: column;
          justify-content: var(--vic-button-align, center);
          background: var(--secondary-background-color, var(--card-background-color, #fff));
        }
        ha-card[transparent] {
          background: transparent;
          box-shadow: none;
          border: none;
        }
        ha-card[isUsingDefault] {
          border: 2px dashed var(--primary-color);
        }
        [role='button'] {
          cursor: pointer;
          pointer-events: auto;
        }
        [role='button']:focus {
          outline: none;
        }
        .background {
          position: absolute;
          top: 0;
          left: 0;
          bottom: 0;
          right: 0;
          border-radius: var(--ha-card-border-radius, 12px);
          margin: calc(-1 * var(--ha-card-border-width, 1px));
          overflow: hidden;
        }
        .highlight {
          background: transparent;
          &::before {
            content: '';
            position: absolute;
            z-index: -2;
            left: -50%;
            top: -50%;
            width: 200%;
            height: 200%;
            background-color: transparent;
            background-repeat: no-repeat;
            background-size: 50% 50%, 50% 50%;
            background-position: 0 0, 100% 0, 100% 100%, 0 100%;
            background-image: linear-gradient(transparent, transparent), linear-gradient(transparent, transparent),
              linear-gradient(transparent, transparent), linear-gradient(var(--primary-color), var(--primary-color));
            animation: rotate 1s linear infinite;
            animation-fill-mode: forwards;
            display: block;
            animation-iteration-count: 2;
          }

          &::after {
            content: '';
            position: absolute;
            z-index: -1;
            left: 2px;
            top: 2px;
            width: calc(100% - 4px);
            height: calc(100% - 4px);
            background: var(--secondary-background-color, var(--card-background-color, #fff));
            border-radius: inherit;
            display: block;
          }
        }
        @keyframes rotate {
          100% {
            transform: rotate(1turn);
          }
        }

        .zoom-in {
          animation-duration: 0.3s;
          animation-fill-mode: both;
          animation-name: zoomIn;
        }

        @keyframes zoomIn {
          from {
            opacity: 0.5;
            transform: scale3d(0.3, 0.3, 0.3);
          }

          to {
            opacity: 1;
          }
        }
      `,
    ];
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'vic-button-card-item': VicButtonCardItem;
  }
}
