import { Subject, of } from 'rxjs';

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

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

import {
  MatDialogRef,
  MAT_DIALOG_DATA,
  MatDialog
} from '@angular/material/dialog';

import { UserInfo, GroupDetailData } from '@ucap/protocol-sync';
import { UserInfoSS, UserInfoF, UserInfoDN } from '@ucap/protocol-query';
import { UserInfo as RoomUserInfo } from '@ucap/protocol-room';
import { MatStepper } from '@angular/material/stepper';
import { I18nService } from '@ucap/ng-i18n';
import { GroupActions } from '@ucap/ng-store-group';
import {
  AlertDialogComponent,
  AlertDialogData,
  AlertDialogResult,
  ConfirmDialogComponent,
  ConfirmDialogResult,
  ConfirmDialogData
} from '@ucap/ng-ui';

import { take, map, catchError } from 'rxjs/operators';

import { SelectUserDialogType, GroupManageType } from '@app/types';
import { AppGroupService } from '@app/services/app-group.service';
import { LogService } from '@ucap/ng-logger';

export type UserInfoTypes =
  | UserInfo
  | UserInfoSS
  | UserInfoF
  | UserInfoDN
  | RoomUserInfo;

export interface ManageDialogData {
  title: string;
  groupBuddyList?: { group: GroupDetailData; buddyList: UserInfo[] };
}
export interface ManageDialogResult {
  type: GroupManageType;
  groupName: string;
  group?: GroupDetailData;
  selelctUserList?: UserInfoTypes[];
  selectGroupList?: GroupDetailData[];
}

@Component({
  selector: 'app-dialog-group-manage',
  templateUrl: './manage.dialog.component.html',
  styleUrls: ['./manage.dialog.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ManageDialogComponent implements OnInit, OnDestroy {
  constructor(
    public dialogRef: MatDialogRef<ManageDialogData, ManageDialogResult>,
    @Inject(MAT_DIALOG_DATA) public data: ManageDialogData,
    private changeDetectorRef: ChangeDetectorRef,
    private store: Store<any>,
    private i18nService: I18nService,
    public dialog: MatDialog,
    private appGroupService: AppGroupService,
    private logService: LogService
  ) {
    this.moveTitle = this.i18nService.t('group:dialog.title.moveGroup');
    this.copyTitle = this.i18nService.t('group:dialog.title.copyGroup');
    this.addTitle = this.i18nService.t('group:dialog.title.addBuddy');
  }

  @ViewChild('dialogContainer', { static: true, read: ViewContainerRef })
  dialogContainer: ViewContainerRef;

  private ngOnDestroySubject: Subject<void>;
  private moveTitle: string;
  private copyTitle: string;
  private addTitle: string;

  title: string;

  GroupManageType = GroupManageType;
  currentManageType: GroupManageType;
  currentStep = 0;
  groupName = '';

  selectedUserList: UserInfoTypes[] = [];
  selectedGroupList: GroupDetailData[] = [];

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

    this.currentManageType = GroupManageType.None;
    this.title = this.data.title;
  }

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

  onClosed(event: MouseEvent): void {
    this.dialogRef.close();
  }

  onDelete(stepper: MatStepper) {
    if (
      !!this.selectedUserList &&
      this.selectedUserList.length > 0 &&
      this.currentStep === 0
    ) {
      let titleStr = '';

      this.selectedUserList.map((user, idx) => {
        let userTitle = user.name + ' ' + user.grade;
        if (this.selectedUserList.length - 1 > idx) {
          userTitle = userTitle + ', ';
          titleStr = titleStr.concat('', userTitle);
        } else {
          titleStr = titleStr.concat('', userTitle);
        }
      });
      this.appGroupService
        .removeMemberToGroup(
          this.i18nService.t('group:dialog.removeBuddyConfirm', {
            targetMember: titleStr
          }),
          this.selectedUserList,
          this.data.groupBuddyList.group
        )
        .then(() => this.dialogRef.close())
        .catch((reson) => this.logService.error(reson));
    }
  }

  onUpdateMember(stepper: MatStepper, type: GroupManageType) {
    this.currentManageType = type;

    if (type === GroupManageType.Move) {
      this.title = this.moveTitle;
    } else {
      this.title = this.copyTitle;
    }

    this.currentStep++;
    stepper.next();
  }

  onAdd(stepper: MatStepper) {
    this.title = this.addTitle;
    this.currentManageType = GroupManageType.Add;
    this.selectedUserList = this.data.groupBuddyList.buddyList;

    this.currentStep++;
    stepper.next();
  }

  onChangeGroupName(data: { invalid: boolean; groupName: string }) {
    this.groupName = data.groupName;
  }

  onSelectBySectionGroup(data: { checked: boolean; group: GroupDetailData }) {
    const i = this.selectedGroupList.findIndex((u) => u.seq === data.group.seq);

    if (data.checked) {
      if (-1 === i) {
        this.selectedGroupList = [...this.selectedGroupList, data.group];
      }
    } else {
      if (-1 < i) {
        this.selectedGroupList = this.selectedGroupList.filter(
          (u) => u.seq !== data.group.seq
        );
      }
    }
  }

  onSelectBySectionUserGroup(params: {
    isChecked: boolean;
    groupBuddyList: { group: GroupDetailData; buddyList: UserInfo[] };
  }) {
    if (params.isChecked) {
      params.groupBuddyList.buddyList.forEach((item) => {
        if (
          this.selectedUserList.filter((user) => user.seq === item.seq)
            .length === 0
        ) {
          this.selectedUserList = [...this.selectedUserList, item];
        }
      });
    } else {
      this.selectedUserList = this.selectedUserList.filter(
        (item) =>
          params.groupBuddyList.buddyList.filter((del) => del.seq === item.seq)
            .length === 0
      );
    }
  }

  doneAnimation() {
    this.changeDetectorRef.markForCheck();
  }
  onChangeSelectedUserList(
    datas: {
      checked: boolean;
      userInfo: UserInfoSS;
    }[]
  ) {
    if (!datas || 0 === datas.length) {
      return;
    }

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

    datas.forEach((d) => {
      const i = this.selectedUserList.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.selectedUserList = [...this.selectedUserList, ...pushs];
    }

    if (0 < pops.length) {
      this.selectedUserList = this.selectedUserList.filter(
        (u) => -1 === pops.findIndex((p) => p.seq === u.seq)
      );
    }
  }
  onCancel(stepper: MatStepper) {
    if (
      !!this.selectedUserList &&
      this.selectedUserList.length > 0 &&
      this.currentManageType === GroupManageType.Add
    ) {
      this.selectedUserList = [];
    } else {
      const tempList = [];
      this.selectedUserList.map((user) => {
        this.data.groupBuddyList.buddyList.every((buddy) => {
          if (user.seq === buddy.seq) {
            tempList.push(user);
            return false;
          }
          return true;
        });
      });
      this.selectedUserList = [...tempList];
    }
    this.selectedGroupList = [];
    this.currentStep--;
    this.title = this.data.title;
    stepper.previous();
  }
  onConfirm(stepper: MatStepper) {
    switch (this.currentManageType) {
      case GroupManageType.Add:
        {
          if (!!this.selectedUserList && this.selectedUserList.length > 0) {
            this.doAction();
          }
        }
        break;
      case GroupManageType.Copy:
      case GroupManageType.Move:
        {
          if (
            !!this.selectedUserList &&
            this.selectedUserList.length === 0 &&
            this.groupName === ''
          ) {
            this.dialog.open<
              AlertDialogComponent,
              AlertDialogData,
              AlertDialogResult
            >(AlertDialogComponent, {
              panelClass: 'min-create-dialog',
              data: {
                title: 'Error',
                html: this.i18nService.t('group:error.notSelectedUser')
              }
            });

            return;
          }

          this.doAction();
        }
        break;
    }
  }

  doAction() {
    if (!!this.groupName && this.groupName.trim().localeCompare('') !== 0) {
      this.currentManageType = GroupManageType.Create;
    } else {
      this.groupName = undefined;
    }

    this.dialogRef.close({
      type: this.currentManageType,
      groupName: this.groupName,
      group: this.data.groupBuddyList.group,
      selelctUserList: this.selectedUserList,
      selectGroupList: this.selectedGroupList
    });
  }

  /** 개별 체크여부 */
  getCheckedUser(userInfo: UserInfoSS) {
    if (!!this.selectedUserList && this.selectedUserList.length > 0) {
      return (
        this.selectedUserList.filter(
          (item) => String(item.seq) === String(userInfo.seq)
        ).length > 0
      );
    }

    return false;
  }

  checkDisableBtn(): boolean {
    let findUser: UserInfoTypes[];
    if (!!this.selectedUserList && this.selectedUserList.length > 0) {
      findUser = this.selectedUserList.filter((user) => {
        return this.data.groupBuddyList.group.userSeqs.includes(
          String(user.seq)
        );
      });
    }

    if (!!findUser && findUser.length > 0) {
      return false;
    } else {
      return true;
    }
  }

  checkDisableBtnConfirm() {
    if (
      (!!this.selectedUserList && this.selectedUserList.length > 0) ||
      (!!this.groupName && this.groupName.trim().localeCompare('') !== 0)
    ) {
      return false;
    }
    return true;
  }
  onToggleCheck(data: { checked: boolean; userInfo: UserInfoSS }) {
    this.onChangeSelectedUserList([data]);
  }

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

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

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

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