import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

import {
  Component,
  OnInit,
  ChangeDetectorRef,
  Input,
  OnDestroy,
  ChangeDetectionStrategy,
  ViewChild
} from '@angular/core';

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

import { SortOrder } from '@ucap/core';
import { LoginResponse } from '@ucap/protocol-authentication';
import { DeptInfo, UserInfoSS } from '@ucap/protocol-query';
import { UserInfo } from '@ucap/protocol-sync';

import { LoginSelector } from '@ucap/ng-store-authentication';
import {
  DepartmentSelector,
  CompanySelector
} from '@ucap/ng-store-organization';

import { SearchData } from '@app/ucap/organization/models/search-data';
import { Company } from '@ucap/api-external';
import { MatCheckboxChange } from '@angular/material/checkbox';
import { ProfileListComponent as AppProfileListComponent } from '@app/ucap/organization/components/profile-list.component';

@Component({
  selector: 'app-sections-organization-member-list',
  templateUrl: './member-list.component.html',
  styleUrls: ['./member-list.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class MemberListComponent implements OnInit, OnDestroy {
  @Input()
  set searchData(searchData: SearchData) {
    this._searchData = searchData;

    if (searchData.bySearch) {
      this.setCompanyInfo(searchData.companyCode);
    } else {
      this.setDeptInfo(searchData.deptSeq);
    }
  }

  @ViewChild('profileList', { static: false })
  profileList: AppProfileListComponent;

  // tslint:disable-next-line: variable-name
  _searchData: SearchData;
  loginRes: LoginResponse;
  selectedDeptInfo: DeptInfo;
  selectedCompanyInfo: Company;
  searchedProfileLength: number;
  selectedUserInfos: UserInfoSS[] = [];
  isExpanded = false;
  sortOrderForProfileList: SortOrder = {
    property: 'name',
    ascending: true
  };

  private ngOnDestroySubject: Subject<void>;

  constructor(
    private store: Store<any>,
    private changeDetectorRef: ChangeDetectorRef
  ) {}

  ngOnInit() {
    this.ngOnDestroySubject = new Subject();

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

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

  onChangedSearch(data: { deptSeq: string; searchWord: string }) {
    this._searchData = {
      bySearch: true,
      ...data
    };
    this.setDeptInfo(data.deptSeq);
  }

  onSearchedProfileList(userInfos: UserInfoSS[]) {
    this.searchedProfileLength = !!userInfos ? userInfos.length : 0;
  }

  onChangedCheckProfileList(
    datas: { checked: boolean; userInfo: UserInfoSS }[]
  ) {
    if (!datas || 0 === datas.length) {
      return;
    }

    const pushs: UserInfoSS[] = [];
    const pops: UserInfoSS[] = [];

    datas.forEach((d) => {
      const i = this.selectedUserInfos.findIndex(
        (u) => u.seq === d.userInfo.seq
      );
      if (d.checked) {
        if (-1 === i) {
          pushs.push(d.userInfo);
        }
      } else {
        if (-1 < i) {
          pops.push(d.userInfo);
        }
      }
    });

    if (0 < pushs.length) {
      this.selectedUserInfos = [...this.selectedUserInfos, ...pushs];
    }

    if (0 < pops.length) {
      this.selectedUserInfos = this.selectedUserInfos.filter(
        (u) => -1 === pops.findIndex((p) => p.seq === u.seq)
      );
    }
  }

  onRemovedProfileSelection(userInfo: UserInfo) {
    const i = this.selectedUserInfos.findIndex(
      (u) => u.seq === String(userInfo.seq)
    );

    if (-1 < i) {
      this.selectedUserInfos = this.selectedUserInfos.filter(
        (u) => u.seq !== String(userInfo.seq)
      );
    }
  }

  removableForSelection = (userInfo: UserInfo) => {
    return true;
  };

  colorForSelection = (userInfo: UserInfo) => {
    return 'accent';
  };

  onOpenedSelection() {
    this.isExpanded = true;
  }

  onClosedSelection() {
    this.isExpanded = false;
  }

  onClickToggleSort() {
    this.sortOrderForProfileList = {
      ...this.sortOrderForProfileList,
      ascending: !this.sortOrderForProfileList.ascending
    };
  }

  onChangeSelectAll(event: MatCheckboxChange) {
    if (event.checked) {
      this.profileList.checkAll();
    } else {
      this.selectedUserInfos = [];
    }
  }

  private setCompanyInfo(companyCode: string) {
    const destroySubject: Subject<void> = new Subject();
    this.store
      .pipe(takeUntil(destroySubject), select(CompanySelector.companyList))
      .subscribe((companyList) => {
        if (!companyList) {
          return;
        }
        this.selectedCompanyInfo = companyList.find(
          (c) => c.companyCode === companyCode
        );
        this.changeDetectorRef.markForCheck();
        destroySubject.next();
        destroySubject.complete();
      });
  }

  private setDeptInfo(seq: string) {
    const destroySubject: Subject<void> = new Subject();
    this.store
      .pipe(
        takeUntil(destroySubject),
        select(DepartmentSelector.departmentInfoList)
      )
      .subscribe((departmentInfoList) => {
        if (!departmentInfoList) {
          return;
        }
        this.selectedDeptInfo = departmentInfoList.find(
          (d) => String(d.seq) === seq
        );
        this.changeDetectorRef.markForCheck();
        destroySubject.next();
        destroySubject.complete();
      });
  }
}
