/**
 * Copyright Aquera Inc 2023
 *
 * This source code is licensed under the BSD-3-Clause license found in the
 * LICENSE file in the root directory of this source tree.
 */

import { LitElement, html, CSSResultArray, TemplateResult, PropertyValues } from 'lit';
import { customElement, state, property } from 'lit/decorators.js';
import {styles} from './nile-link.css';
import { HasSlotController } from '../slot';
import { ifDefined } from 'lit/directives/if-defined.js';
import { classMap } from 'lit/directives/class-map.js';
import NileElement, { setupA11yMetadata } from '../internal/nile-element';
import { watch } from '../internal/watch';
import { A11yProperty } from '../internal/accessibility/a11y.property.enum';
import { Role } from '../internal/accessibility/role.enum';
import { A11yCustomValue } from '../internal/accessibility/a11y.custom-value.enum';
import { A11yRole } from '../internal/accessibility/a11y.role.enum';
import { A11yState } from '../internal/accessibility/a11y.state.enum';

/**
 * Nile icon component.
 *
 * @tag nile-link
 *
 */
@customElement('nile-link')
export class NileLink extends NileElement {
  /**
   * The styles for Link
   * @remarks If you are extending this class you can extend the base styles with super. Eg `return [super(), myCustomStyles]`
   */
  public static get styles(): CSSResultArray {
    return [styles];
  }

  private readonly hasSlotController = new HasSlotController(
    this,
    '[default]',
    'prefix',
    'suffix'
  );

  @state() private hasFocus = false;

  /** Disables the button. */
  @property({ type: Boolean, reflect: true }) disabled = false;

  @property({ type: Boolean }) button = false;

  @property({ type: String }) href:string;

  connectedCallback() {
    super.connectedCallback();
    this.handleHostClick = this.handleHostClick.bind(this);
    this.addEventListener('click', this.handleHostClick);
    this.emit('nile-init');

    setupA11yMetadata(this, {
      [Role.Role]: A11yRole.Link,
      [A11yProperty.AriaLabel]: this.textContent?.trim() || A11yCustomValue.Link,
    });
  }

  protected updated(_changedProperties: PropertyValues): void {
    super.updated(_changedProperties);
    if (_changedProperties.has('disabled')) {
      setupA11yMetadata(this, {
        [A11yState.AriaDisabled]: this.disabled,
      });
    }
  }

  disconnectedCallback() {
    super.disconnectedCallback();
    this.removeEventListener('click', this.handleHostClick);
    this.emit('nile-destroy');
  }

  private handleHostClick(event: MouseEvent) {
    // Prevent the click event from being emitted when the button is disabled
    if (this.disabled) {
      event.preventDefault();
      event.stopImmediatePropagation();
      event.stopPropagation();
    }
  }

  private handleBlur() {
    this.hasFocus = false;
    this.emit('nile-blur');
  }

  private handleFocus() {
    this.hasFocus = true;
    this.emit('nile-focus');
  }

  handleClick(e: MouseEvent) {
    if (this.disabled) {
      e.preventDefault();
      e.stopPropagation();
      return;
    }
  }

  /**
   * Render method
   * @slot This is a slot test
   */
  public render(): TemplateResult {
    return html`
      <a
        part="base"
        href="${ifDefined(this.href)}"
        class=${classMap({
          'link': true,
          'link--disabled': this.disabled,
          'link__button': this.button,
        })}
        .disabled=${this.disabled}
        title=${
          this
            .title /* An empty title prevents browser validation tooltips from appearing on hover */
        }
        aria-disabled=${this.disabled ? 'true' : 'false'}
        tabindex=${this.disabled ? '-1' : '0'}
        @blur=${this.handleBlur}
        @focus=${this.handleFocus}
        @click=${this.handleClick}
      >
        <slot name="prefix" part="prefix" class="link__prefix"></slot>
        <slot part="label" class="link__label"></slot>
        <slot name="suffix" part="suffix" class="link__suffix"></slot>
      </a>
    `;
  }

  /* #endregion */
}

export default NileLink;

declare global {
  interface HTMLElementTagNameMap {
     'nile-link': NileLink;
   }
 }
