import {
  ChangeDetectionStrategy,
  Component,
  EventEmitter,
  Input,
  OnChanges,
  Output,
  SimpleChanges,
} from '@angular/core';
import { DropdownTriggerForDirective } from '@msfa-shared/components/dropdown/dropdown-trigger-for.directive';
import { MultiselectFilterOption } from '@msfa-shared/components/multiselect/multiselect-filter-option';
import { BehaviorSubject } from 'rxjs';

@Component({
  selector: 'msfa-multiselect-panel',
  templateUrl: './multiselect-panel.component.html',
  styleUrls: ['./multiselect-panel.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MultiselectPanelComponent implements OnChanges {
  @Input() dropdownRef: DropdownTriggerForDirective;
  @Input() confirmButtonText = 'Spara';
  @Input() multiselectTitle: string;
  @Input() multiselectTitlePlural: string;
  @Input() description: string;
  @Input() availableOptions: MultiselectFilterOption[];
  @Input() selectedOptions: MultiselectFilterOption[];
  @Output() selectedOptionsChange = new EventEmitter<MultiselectFilterOption[]>();

  private _pendingSelectedOptions$ = new BehaviorSubject<MultiselectFilterOption[]>([]);
  private _selectedUnavailableOptions$ = new BehaviorSubject<MultiselectFilterOption[]>([]);

  ngOnChanges(changes: SimpleChanges): void {
    if (changes.availableOptions || changes.selectedOptions) {
      this._setPendingSelectedOptions();
    }
  }
  get selectedUnavailableOptions(): MultiselectFilterOption[] {
    return this._selectedUnavailableOptions$.getValue();
  }
  private get _pendingSelectedOptions(): MultiselectFilterOption[] {
    return this._pendingSelectedOptions$.getValue();
  }

  private _setPendingSelectedOptions(): void {
    this._pendingSelectedOptions$.next(this.selectedOptions || []);
    this._selectedUnavailableOptions$.next(
      this.selectedOptions?.filter(
        selectedOption => !this.availableOptions.some(availableOption => availableOption.id === selectedOption.id)
      ) || []
    );
  }

  isSelected(filterOption: MultiselectFilterOption): boolean {
    return this._pendingSelectedOptions$.value?.some(selectedOption => selectedOption.id === filterOption.id) ?? false;
  }

  emitSelectedOptions(): void {
    this.selectedOptionsChange.emit(this._pendingSelectedOptions);
  }

  setOptionState(filterOption: MultiselectFilterOption, isSelected: boolean): void {
    if (isSelected) {
      this._pendingSelectedOptions$.next([...this._pendingSelectedOptions, filterOption]);
    } else {
      this._pendingSelectedOptions$.next(
        this._pendingSelectedOptions.filter(item => item.id !== filterOption.id) ?? []
      );
    }
  }
}
