import {CommonModule} from '@angular/common';
import {
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  ElementRef,
  EventEmitter,
  HostBinding,
  HostListener,
  inject,
  Input,
  Output,
  ViewEncapsulation,
} from '@angular/core';
import {CheckboxComponent} from '../checkbox/checkbox.component';
import {IconComponent} from '../icon/icon.component';

import {TListItemType} from './list-item.model';

@Component({
  /* eslint-disable-next-line @angular-eslint/component-selector */
  selector: '[nj-list-item]',
  templateUrl: './list-item.component.html',
  styleUrls: ['./list-item.component.scss'],
  encapsulation: ViewEncapsulation.None,
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: true,
  imports: [IconComponent, CheckboxComponent, CommonModule]
})
export class ListItemComponent {

  private readonly cdr = inject(ChangeDetectorRef);

  /**
   * @ignore
   */
  @HostBinding('class')
  get className() {
    return 'nj-list-deprecated__item';
  }

  /**
   * Whether item is active or not
   */
  @HostBinding('class.nj-list-deprecated__item--active')
  @Input()
  isActive: boolean;

  /**
   * Whether item is disabled or not
   */
  @HostBinding('class.nj-list-deprecated__item--disabled')
  @Input()
  isDisabled: boolean;

  /**
   * @ignore
   */
  @HostBinding('class.nj-list-deprecated__item--clickable')
  get isClickable() {
    const hasRoleOption = this.role === 'option';
    return this.hasClickableChildren || hasRoleOption;
  }

  /**
   * Whether the border should be on the right
   */
  @HostBinding('class.nj-list-deprecated__item--right-border')
  @Input()
  hasRightBorder = false;

  /** Override aria role if required. */
  @HostBinding('attr.role')
  @Input()
  role?: string;

  /**
   * @ignore
   */
  @HostBinding('attr.tabindex')
  get getTabindex() {
    return this.role === 'option' ? -1 : null;
  }

  @HostBinding('attr.aria-selected')
  @Input()
  ariaSelected: boolean = null;

  /**
   * Name of the icon
   */
  @Input() iconName: string;

  /**
   * Aria label of the icon
   */
  @Input() iconAriaLabel: string;

  /**
   * List item type <br>
   * `list` -> `<li>...</li>` <br>
   * `link` -> `<li><a>...</a></li>` <br>
   * `button` -> `<li><button>...</button></li>`
   *
   * @default "list"
   */
  @Input() type?: TListItemType;

  /**
   * List item href when `type` is `link`
   */
  @Input() href?: string;

  /**
   * List item attribute value
   */
  @Input() value: string;

  /**
   * Whether content should be in a checkbox
   */
  @Input() isCheckboxContent: boolean = false;

  /**
   * Whether only icon should be displayed
   */
  @Input() isIconOnly: boolean = false;

  /**
   * Checkbox id if `isCheckboxContent` is set to `true`
   */
  @Input() checkboxContentId: string;

  /**
   * Emits an event on item click
   */
  @Output() itemClick = new EventEmitter<MouseEvent>();

  /**
   * @ignore
   */
  @HostListener('click', ['$event']) onMouseClick(event: MouseEvent) {
    // Ignore the event if the list item is a button or a link, the click event is bound to
    // the wrapped <button> or <a>
    if (!this.hasClickableChildren) {
      this.itemClick.emit(event);
    }
  }

  constructor(public readonly el: ElementRef<HTMLElement>) {
  }

  /**
   * Get value of item, returns value if set else returns textContent of item.
   * Used in `<nj-select>` component
   */
  getValue(): string {
    return this.value ?? this.getLabel();
  }

  /**
   * Get label of item, returns textContent of item.
   * Used in `<nj-select>` component
   */
  getLabel(): string {
    return this.el?.nativeElement?.textContent;
  }

  /**
   * @ignore
   */
  updateSelected(isSelected: boolean) {
    this.ariaSelected = isSelected;
    this.isActive = isSelected;
    this.cdr.markForCheck();
  }

  /**
   * @ignore
   */
  get hasClickableChildren() {
    return this.type === 'button' || this.type === 'link';
  }
}
