import {
  Component,
  OnInit,
  OnDestroy,
  Output,
  EventEmitter,
  ChangeDetectorRef,
  ChangeDetectionStrategy,
  ViewChild
} from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';

import { Store, select } from '@ngrx/store';

import { LogService } from '@ucap/ng-logger';
import { takeUntil, debounceTime } from 'rxjs/operators';
import { Subject, combineLatest } from 'rxjs';

import { RoomSelector } from '@ucap/ng-store-chat';
import { LoginSelector } from '@ucap/ng-store-authentication';

import { LoginResponse } from '@ucap/protocol-authentication';
import { MatAutocompleteTrigger } from '@angular/material/autocomplete';

@Component({
  selector: 'app-sections-chat-search',
  templateUrl: './search.section.component.html',
  styleUrls: ['./search.section.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class SearchSectionComponent implements OnInit, OnDestroy {
  @Output()
  keyDownEnter = new EventEmitter<{
    searchWord: string;
  }>();

  @Output()
  searchCancel = new EventEmitter<any>();

  loginRes: LoginResponse;

  fgSearch: FormGroup;
  recommendedWordList: string[];
  filteredRecommendedWordList: string[];

  @ViewChild(MatAutocompleteTrigger) autocomplete: MatAutocompleteTrigger;

  private ngOnDestroySubject: Subject<boolean>;

  constructor(
    private store: Store<any>,
    private formBuilder: FormBuilder,
    private changeDetectorRef: ChangeDetectorRef,
    private logService: LogService
  ) {}

  ngOnInit(): void {
    this.ngOnDestroySubject = new Subject<boolean>();

    this.fgSearch = this.formBuilder.group({
      searchInput: null
    });

    this.fgSearch
      .get('searchInput')
      .valueChanges.pipe(debounceTime(100))
      .subscribe((value) => {
        if (value !== null && value.length > 0) {
          this.filteredRecommendedWordList = this.recommendedWordList.filter(
            (v) => {
              return v.includes(value);
            }
          );
        } else {
          this.filteredRecommendedWordList = [];
        }

        this.changeDetectorRef.detectChanges();
      });

    this.store
      .pipe(takeUntil(this.ngOnDestroySubject), select(LoginSelector.loginRes))
      .subscribe((loginRes) => {
        this.loginRes = loginRes;
      });

    combineLatest([
      this.store.pipe(select(RoomSelector.rooms)),
      this.store.pipe(select(RoomSelector.roomUsers)),
      this.store.pipe(select(RoomSelector.roomUsersShort))
    ])
      .pipe(takeUntil(this.ngOnDestroySubject))
      .subscribe(([rooms, roomUsers, roomUsersShort]) => {
        rooms = rooms || [];
        roomUsers = roomUsers || [];
        roomUsersShort = roomUsersShort || [];

        const recommendedWordList = [];
        for (const r of rooms) {
          if (!!r.roomName && '' !== r.roomName.trim()) {
            recommendedWordList.push(r.roomName);
          }
        }
        for (const ru of roomUsers) {
          for (const u of ru.userInfos) {
            if (!!this.loginRes && u.seq !== Number(this.loginRes.userSeq)) {
              if (!!u.name && '' !== u.name.trim() && u.isJoinRoom) {
                recommendedWordList.push(u.name);
              }
            }
          }
        }
        for (const ru of roomUsersShort) {
          for (const u of ru.userInfos) {
            if (!!this.loginRes && u.seq !== Number(this.loginRes.userSeq)) {
              if (!!u.name && '' !== u.name.trim() && u.isJoinRoom) {
                recommendedWordList.push(u.name);
              }
            }
          }
        }
        this.recommendedWordList = [
          ...recommendedWordList.filter(
            (item, index) => recommendedWordList.indexOf(item) === index
          )
        ];
      });
  }

  ngOnDestroy(): void {
    if (!!this.ngOnDestroySubject) {
      this.ngOnDestroySubject.complete();
    }
  }

  onKeyDownEnter(event: KeyboardEvent, searchWord: string) {
    event.preventDefault();
    event.stopPropagation();

    this.autocomplete.closePanel();

    this.keyDownEnter.emit({ searchWord });
  }
  onClickCancel() {
    this.searchCancel.emit();
  }
}
