import { Subject, of } from 'rxjs';

import {
  Component,
  OnInit,
  OnDestroy,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Inject,
  ComponentFactoryResolver,
  ViewChild,
  ViewContainerRef,
  ComponentRef
} 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 { SelectUserSectionComponent } from '../components/select-user.section.component';
import { take, map, catchError } from 'rxjs/operators';
import { SelectGroupSectionComponent } from '../components/select-group.section.component';
import { SelectUserDialogType, GroupUserDialaogType } from '@app/types';

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

export enum ManageContentType {
  Add = 'ADD_COMPONENT',
  Copy = 'COPY_COMPONENT',
  Move = 'MOVE_COMPONENT',
  Delete = 'DELETE_COMPONENT',
  None = 'NONE_COMPONENT'
}
export interface ManageDialogData {
  title: string;
  groupBuddyList?: { group: GroupDetailData; buddyList: UserInfo[] };
}
export interface ManageDialogResult {
  type: GroupUserDialaogType;
  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 cfResolver: ComponentFactoryResolver
  ) {}

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

  componentRef: ComponentRef<any>;
  private ngOnDestroySubject: Subject<void>;
  currentType: GroupUserDialaogType;
  SelectUserDialogType = SelectUserDialogType;
  GroupUserDialaogType = GroupUserDialaogType;

  currentStep = 0;
  groupName = '';

  ManageContentType = ManageContentType;

  selectedUserList: UserInfoTypes[];
  selectedGroupList: GroupDetailData[];
  selectContentType: ManageContentType;

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

    this.selectedUserList = [];
    this.selectContentType = ManageContentType.None;
  }

  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.forEach((user, idx) => {
        let userTitle = user.name + ' ' + user.grade;
        if (idx < this.selectedUserList.length) {
          userTitle = userTitle + ', ';
        }
        titleStr = titleStr.concat('', userTitle);
      });
      const dialogRef = this.dialog.open<
        ConfirmDialogComponent,
        ConfirmDialogData,
        ConfirmDialogResult
      >(ConfirmDialogComponent, {
        panelClass: 'min-create-dialog',
        data: {
          title: '동료 삭제',
          html: titleStr + '을 삭제하시겠습니까?'
        }
      });
      dialogRef
        .afterClosed()
        .pipe(
          take(1),
          map((result) => {
            if (!!result && result.choice) {
              const trgtUserSeq: string[] = [];

              this.selectedUserList.forEach((userIfno) => {
                const tempSeqs = this.data.groupBuddyList.group.userSeqs.filter(
                  (seq) => seq !== userIfno.seq
                );

                tempSeqs.map((seq) => trgtUserSeq.push(seq));
              });

              console.log(trgtUserSeq);

              this.store.dispatch(
                GroupActions.updateMember({
                  targetGroup: this.data.groupBuddyList.group,
                  targetUserSeqs: trgtUserSeq
                })
              );
              this.dialogRef.close();
            }
          }),
          catchError((err) => {
            return of(err);
          })
        )
        .subscribe();
    }
  }
  onUpdateMember(stepper: MatStepper, type: GroupUserDialaogType) {
    this.dialogContainer.clear();
    this.currentType = type;
    this.selectedGroupList = [];
    const isMemberMove = type === GroupUserDialaogType.Copy ? false : true;

    const factory = this.cfResolver.resolveComponentFactory(
      SelectGroupSectionComponent
    );

    this.componentRef = this.dialogContainer.createComponent(factory);
    const cpInstance = this.componentRef.instance;
    // cpInstance.title = title;
    cpInstance.isMemberMove = isMemberMove;
    cpInstance.isDialog = true;
    cpInstance.checkable = true;
    cpInstance.curGroup = this.data.groupBuddyList.group;
    cpInstance.selectedGroupList = this.selectedGroupList;
    cpInstance.selectedUserList = this.selectedUserList;
    cpInstance.changeUserList.subscribe(
      (datas: { checked: boolean; userInfo: UserInfoSS }[]) => {
        this.changeSelectedUserList(datas);
        cpInstance.selectedUserList = this.selectedUserList;
      }
    );
    cpInstance.changeGroupList.subscribe((data: { group: GroupDetailData }) => {
      if (
        this.selectedGroupList.filter((g) => g.seq === data.group.seq)
          .length === 0
      ) {
        this.selectedGroupList = [...this.selectedGroupList, data.group];
      } else {
        this.selectedGroupList = this.selectedGroupList.filter(
          (g) => g.seq !== data.group.seq
        );
      }
      cpInstance.selectedGroupList = this.selectedGroupList;
    });
    cpInstance.changeGroupName.subscribe((groupName) => {
      this.groupName = groupName;
    });
    this.currentStep++;
    stepper.next();
  }

  onAdd(stepper: MatStepper) {
    this.dialogContainer.clear();
    this.currentType = GroupUserDialaogType.Add;

    const factory = this.cfResolver.resolveComponentFactory(
      SelectUserSectionComponent
    );

    this.componentRef = this.dialogContainer.createComponent(factory);
    const cpInstance = this.componentRef.instance;
    cpInstance.isDialog = true;
    cpInstance.checkable = true;
    cpInstance.selectedUserList = this.data.groupBuddyList.buddyList;

    // const cpElement: HTMLElement = this.componentRef.location.nativeElement;
    // cpElement.style.height = '400px';

    cpInstance.toggleCheckUser.subscribe(
      (datas: { checked: boolean; userInfo: UserInfoSS }[]) => {
        this.changeSelectedUserList(datas);
        cpInstance.selectedUserList = this.selectedUserList;
      }
    );

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

  onChangeUserList(datas: { checked: boolean; userInfo: UserInfoSS }[]) {
    this.changeSelectedUserList(datas);
  }

  private changeSelectedUserList(
    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)
      );
    }
  }
  onCnacel(stepper: MatStepper) {
    if (!!this.selectedUserList && this.selectedUserList.length > 0) {
      this.selectedUserList = [];
    }
    this.currentStep--;
    stepper.previous();
  }
  onConfirm(stepper: MatStepper) {
    switch (this.currentType) {
      case GroupUserDialaogType.Add:
        {
          if (!!this.selectedUserList && this.selectedUserList.length > 0) {
            this.doAction();
          }
        }
        break;
      case GroupUserDialaogType.Copy:
      case GroupUserDialaogType.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: '선택된 유저가 없습니다.'
              }
            });

            return;
          }

          this.doAction();
        }
        break;
    }
  }

  doAction() {
    this.dialogContainer.clear();
    if (!!this.groupName && this.groupName.trim().localeCompare('') !== 0) {
      this.currentType = GroupUserDialaogType.Create;
    } else {
      this.groupName = undefined;
    }

    this.dialogRef.close({
      type: this.currentType,
      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) => (item.seq as any) === (userInfo.seq as any)
        ).length > 0
      );
    }

    return false;
  }

  onToggleCheck(data: { checked: boolean; userInfo: UserInfoSS }) {
    this.changeSelectedUserList([data]);
  }

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

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

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

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