import {
  Component,
  OnInit,
  OnDestroy,
  Output,
  EventEmitter,
  Input,
  ViewChild,
  AfterViewInit,
  AfterContentChecked,
  AfterViewChecked
} from '@angular/core';
import { ucapAnimations, DialogService } from '@ucap-webmessenger/ui';
import { Observable, Subscription, of } from 'rxjs';
import {
  DeptInfo,
  QueryProtocolService,
  DeptSearchType,
  UserInfoSS,
  DeptUserResponse,
  UserInfoF,
  UserInfoDN,
  SSVC_TYPE_QUERY_DEPT_USER_DATA,
  SSVC_TYPE_QUERY_DEPT_USER_RES,
  DeptUserData
} from '@ucap-webmessenger/protocol-query';
import { UserInfo, GroupDetailData } from '@ucap-webmessenger/protocol-sync';
import { Store, select } from '@ngrx/store';
import { NGXLogger } from 'ngx-logger';

import * as AppStore from '@app/store';
import * as QueryStore from '@app/store/messenger/query';
import * as SyncStore from '@app/store/messenger/sync';
import * as ChatStore from '@app/store/messenger/chat';
import * as StatusStore from '@app/store/messenger/status';
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
import { LoginInfo, KEY_LOGIN_INFO } from '@app/types';
import { take, map, tap, delay, catchError } from 'rxjs/operators';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { KEY_VER_INFO } from '@app/types/ver-info.type';
import {
  SelectGroupDialogComponent,
  SelectGroupDialogData,
  SelectGroupDialogResult
} from '../../dialogs/group/select-group.dialog.component';
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
import { Company } from '@ucap-webmessenger/api-external';
import { PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';

@Component({
  selector: 'app-layout-chat-left-sidenav-organization',
  templateUrl: './organization.component.html',
  styleUrls: ['./organization.component.scss'],
  animations: ucapAnimations
})
export class OrganizationComponent
  implements OnInit, OnDestroy, AfterViewChecked {
  @Input()
  showTitle = true;
  @Input()
  /** 사용자 선택용으로 사용시 true 로 유입 */
  isUserSelect = false;
  @Input()
  /** 선택된 사용자의 리스트 */
  selectedUserList?: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[] = [];
  @Input()
  isVisible = true;

  @Output()
  checkUser = new EventEmitter<{
    isChecked: boolean;
    userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN;
  }>();
  @Output()
  toggleUser = new EventEmitter<
    UserInfo | UserInfoSS | UserInfoF | UserInfoDN
  >();
  @Output()
  checkAllUser = new EventEmitter<{
    isChecked: boolean;
    userInfos: (UserInfo | UserInfoSS | UserInfoF | UserInfoDN)[];
  }>();
  @Output()
  openProfile = new EventEmitter<
    UserInfo | UserInfoSS | UserInfoF | UserInfoDN
  >();

  @ViewChild('cvsvDeptUser', { static: false })
  cvsvDeptUser: CdkVirtualScrollViewport;

  companyList$: Observable<Company[]>;
  companyCode: string;

  departmentInfoList$: Observable<DeptInfo[]>;
  selectedDepartmentUserInfoList: UserInfoSS[] = [];
  selectedDepartmentUserInfoListSubscription: Subscription;
  selectedDepartmentStatus$: Observable<DeptUserResponse>;
  selectedDepartmentProcessing = false;
  selectedDepartmentProcessingSubscription: Subscription;
  selectedDepartmentName: string;

  loginInfo: LoginInfo;
  loginRes: LoginResponse;
  sessionVerinfo: VersionInfo2Response;

  isShowSearch = false;
  searchUserInfos: UserInfoSS[] = [];

  /** 부서원 리스트에 virture scroll의 size 가 체킹되지 않아 강제 수행. 1번만. */
  isInitList = false;

  constructor(
    private store: Store<any>,
    private sessionStorageService: SessionStorageService,
    private queryProtocolService: QueryProtocolService,
    private dialogService: DialogService,
    private logger: NGXLogger
  ) {
    this.loginInfo = this.sessionStorageService.get<LoginInfo>(KEY_LOGIN_INFO);
    this.sessionVerinfo = this.sessionStorageService.get<VersionInfo2Response>(
      KEY_VER_INFO
    );
  }

  ngOnInit() {
    this.companyCode = this.loginInfo.companyCode;
    this.companyList$ = this.store.pipe(
      select(AppStore.SettingSelector.CompanySelector.companyList)
    );

    this.departmentInfoList$ = this.store.pipe(
      select(AppStore.MessengerSelector.QuerySelector.departmentInfoList)
    );

    this.selectedDepartmentProcessingSubscription = this.store
      .pipe(
        delay(0),
        select(
          AppStore.MessengerSelector.QuerySelector.selectedDepartmentProcessing
        ),
        tap(processing => {
          this.selectedDepartmentProcessing = processing;
        })
      )
      .subscribe();

    this.selectedDepartmentUserInfoListSubscription = this.store
      .pipe(
        select(
          AppStore.MessengerSelector.QuerySelector
            .selectedDepartmentUserInfoList
        ),
        map(list => {
          this.selectedDepartmentUserInfoList = list;
        })
      )
      .subscribe();

    this.selectedDepartmentStatus$ = this.store.pipe(
      select(AppStore.MessengerSelector.QuerySelector.selectedDepartmentStatus)
    );

    this.store
      .pipe(
        take(1),
        select(AppStore.AccountSelector.AuthenticationSelector.loginRes),
        map(loginRes => {
          this.store.dispatch(
            QueryStore.deptUser({
              divCd: 'ORG',
              companyCode: this.loginInfo.companyCode,
              seq: loginRes.departmentCode,
              search: '',
              searchRange: DeptSearchType.All,
              senderCompanyCode: this.loginInfo.companyCode,
              senderEmployeeType: loginRes.userInfo.employeeType
            })
          );
          return loginRes;
        }),
        map(loginRes => {
          this.loginRes = loginRes;
          this.selectedDepartmentName = loginRes.userInfo.deptName;
        })
      )
      .subscribe();
  }

  ngAfterViewChecked(): void {
    if (
      !!this.cvsvDeptUser &&
      !!this.selectedDepartmentUserInfoList &&
      this.selectedDepartmentUserInfoList.length > 0 &&
      !this.isInitList &&
      this.isVisible
    ) {
      this.isInitList = true;
      this.cvsvDeptUser.checkViewportSize();
    }
  }

  ngOnDestroy(): void {
    if (!!this.selectedDepartmentUserInfoListSubscription) {
      this.selectedDepartmentUserInfoListSubscription.unsubscribe();
    }
    if (!!this.selectedDepartmentProcessingSubscription) {
      this.selectedDepartmentProcessingSubscription.unsubscribe();
    }
  }

  /** 유저검색 */
  onKeyDownEnterOrganizationTenantSearch(params: {
    companyCode: string;
    searchWord: string;
  }) {
    if (params.searchWord.trim().length > 1) {
      this.isShowSearch = true;
      this.selectedDepartmentProcessing = true;
      const searchUserInfos: UserInfoSS[] = [];
      this.queryProtocolService
        .deptUser({
          divCd: 'GRP',
          companyCode: params.companyCode,
          searchRange: DeptSearchType.All,
          search: params.searchWord,
          senderCompanyCode: params.companyCode,
          senderEmployeeType: this.loginRes.userInfo.employeeType
        })
        .pipe(
          map(res => {
            switch (res.SSVC_TYPE) {
              case SSVC_TYPE_QUERY_DEPT_USER_DATA:
                searchUserInfos.push(...(res as DeptUserData).userInfos);
                break;
              case SSVC_TYPE_QUERY_DEPT_USER_RES:
                {
                  // 검색 결과 처리.
                  this.searchUserInfos = searchUserInfos;
                  this.selectedDepartmentProcessing = false;
                  // 검색 결과에 따른 프레즌스 조회.
                  const userSeqList: number[] = [];
                  this.searchUserInfos.map(user => userSeqList.push(user.seq));
                  if (userSeqList.length > 0) {
                    this.store.dispatch(
                      StatusStore.bulkInfo({
                        divCd: 'orgSrch',
                        userSeqs: userSeqList
                      })
                    );
                  }
                }
                break;
            }
          }),
          catchError(error => {
            this.selectedDepartmentProcessing = false;
            return of(this.logger.error(error));
          })
        )
        .subscribe();
    }
  }
  /** 검색 취소 */
  onClickCancel() {
    this.isShowSearch = false;
    this.searchUserInfos = [];
  }

  onSelectedOrganization(deptInfo: DeptInfo) {
    this.onClickCancel();

    this.store
      .pipe(
        take(1),
        select(AppStore.AccountSelector.AuthenticationSelector.loginRes),
        map(loginRes => {
          this.store.dispatch(
            QueryStore.deptUser({
              divCd: 'ORG',
              companyCode: this.loginInfo.companyCode,
              seq: deptInfo.seq,
              search: '',
              searchRange: DeptSearchType.All,
              senderCompanyCode: this.loginInfo.companyCode,
              senderEmployeeType: loginRes.userInfo.employeeType
            })
          );
        }),
        map(() => {
          this.selectedDepartmentName = deptInfo.name;
        })
      )
      .subscribe();
  }

  getSelectedDepartmentName() {
    if (!!this.selectedDepartmentProcessing) {
      return '조회중..';
    }

    if (!!this.selectedDepartmentName) {
      return this.selectedDepartmentName;
    } else {
      return '조회중..';
    }
  }

  /** 전체 체크여부 */
  getCheckedAllUser() {
    const compareList: UserInfoSS[] = this.isShowSearch
      ? this.searchUserInfos
      : this.selectedDepartmentUserInfoList;

    if (
      !compareList ||
      compareList.length === 0 ||
      compareList.filter(
        item =>
          !(
            this.selectedUserList.filter(user => user.seq === item.seq).length >
            0
          )
      ).length > 0
    ) {
      return false;
    } else {
      return true;
    }
  }
  /** 리스트 checkable 할 경우 checkbox 의 isChecked 를 관장하며 리스트의 전체선택 여부를 판단한다. */
  getCheckedUser(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) {
    if (!!this.selectedUserList && this.selectedUserList.length > 0) {
      return (
        this.selectedUserList.filter(item => item.seq === userInfo.seq).length >
        0
      );
    }
    return false;
  }

  /** 전체선택 이벤트 */
  onCheckAllUser(value: boolean) {
    this.checkAllUser.emit({
      isChecked: value,
      userInfos: this.isShowSearch
        ? this.searchUserInfos
        : this.selectedDepartmentUserInfoList
    });
  }

  /** 리스트가 checkable 할 경우 checkbox 의 change 이벤트를 상위 컴포넌트로 전달한다. */
  onCheckUser(params: {
    isChecked: boolean;
    userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN;
  }) {
    this.checkUser.emit(params);
  }
  onToggleUser(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) {
    this.toggleUser.emit(userInfo);
  }

  onClickOpenProfile(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) {
    this.openProfile.emit(userInfo);
  }

  onClickShowSelectedUserList() {
    this.logger.debug('onClickShowSelectedUserList', this.selectedUserList);
  }

  async onClickAddGroup() {
    this.logger.debug('onClickAddGroup', this.selectedUserList);

    const result = await this.dialogService.open<
      SelectGroupDialogComponent,
      SelectGroupDialogData,
      SelectGroupDialogResult
    >(SelectGroupDialogComponent, {
      width: '600px',
      data: {
        title: 'Group Select'
      }
    });

    if (!!result && !!result.choice && result.choice) {
      if (!!result.group) {
        const oldGroup: GroupDetailData = result.group;
        const trgtUserSeq: number[] = [];
        result.group.userSeqs.map(seq => trgtUserSeq.push(seq));
        this.selectedUserList
          .filter(v => result.group.userSeqs.indexOf(v.seq) < 0)
          .forEach(user => {
            trgtUserSeq.push(user.seq);
          });

        this.store.dispatch(
          SyncStore.updateGroupMember({
            oldGroup,
            trgtUserSeq
          })
        );

        // 상위 컴포넌트의 selectedUserList clear.
        this.checkAllUser.emit({
          isChecked: false,
          userInfos: this.selectedUserList
        });
      }
    }
  }
  onClickChatOpen() {
    if (!!this.selectedUserList && this.selectedUserList.length > 0) {
      const seq: number[] = [];
      this.selectedUserList.map(user => seq.push(user.seq));
      this.store.dispatch(ChatStore.openRoom({ userSeqList: seq }));
    }
  }
  onClickConference() {
    this.logger.debug('onClickConference', this.selectedUserList);
  }
}
