import {
  Component,
  OnInit,
  Input,
  Output,
  EventEmitter,
  ViewChild,
  ElementRef,
  ChangeDetectorRef
} from '@angular/core';
import {
  FormControl,
  FormGroup,
  Validators,
  ValidatorFn,
  AbstractControl,
  ValidationErrors,
  FormBuilder
} from '@angular/forms';
import {
  PasswordUtil,
  PasswordValidationOption,
  PasswordValidationResult
} from '@ucap-webmessenger/pi';

export function ucapPassword(option: PasswordValidationOption): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    const result = PasswordUtil.validate(control.value, option);
    return PasswordValidationResult.Valid !== result.code
      ? { ucapPassword: { result } }
      : null;
  };
}

export function ucapPasswordSame(value: string): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    return !!value && value !== PasswordUtil.encrypt(control.value)
      ? { ucapPasswordSame: true }
      : null;
  };
}

export function ucapNotSameWith(targetControl: AbstractControl): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    return !!targetControl &&
      (targetControl.value as string) === (control.value as string)
      ? { ucapNotSameWith: true }
      : null;
  };
}

export function ucapSameWith(targetControl: AbstractControl): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    return !!targetControl && targetControl.value !== control.value
      ? { ucapSameWith: true }
      : null;
  };
}

export function ucapNotSame(value: string | number): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    return !!value && value === control.value ? { ucapNotSame: true } : null;
  };
}

export function ucapSame(value: string | number): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    return !!value && value !== control.value ? { ucapSame: true } : null;
  };
}

@Component({
  selector: 'ucap-account-change-password',
  templateUrl: './change-password.component.html',
  styleUrls: ['./change-password.component.scss']
})
export class ChangePasswordComponent implements OnInit {
  @Input()
  loginId: string;

  @Input()
  phoneNumber: string;

  @Input()
  encryptedLoginPw: string;

  @Output()
  changePassword = new EventEmitter<{
    currentLoginPw: string;
    newLoginPw: string;
  }>();

  changePasswordForm: FormGroup;
  currentLoginPwFormControl = new FormControl('');
  newLoginPwFormControl = new FormControl('');
  newConfirmLoginPwFormControl = new FormControl('');

  PasswordValidationResult = PasswordValidationResult;

  constructor(
    private formBuilder: FormBuilder,
    private changeDetectorRef: ChangeDetectorRef
  ) {}

  ngOnInit() {
    const currentLoginPwValidators: ValidatorFn[] = [Validators.required];
    if (!!this.encryptedLoginPw) {
      currentLoginPwValidators.push(ucapPasswordSame(this.encryptedLoginPw));
    }
    this.currentLoginPwFormControl.setValidators(currentLoginPwValidators);

    let validateOption: PasswordValidationOption = {};
    if (!!this.loginId) {
      validateOption = {
        ...validateOption,
        userId: this.loginId
      };
    }
    if (!!this.phoneNumber) {
      validateOption = {
        ...validateOption,
        phoneNumber: this.phoneNumber
      };
    }

    const newLoginPwValidators: ValidatorFn[] = [
      Validators.required,
      ucapNotSameWith(this.currentLoginPwFormControl),
      ucapPassword(validateOption)
    ];
    this.newLoginPwFormControl.setValidators(newLoginPwValidators);

    const newConfirmLoginPwValidators: ValidatorFn[] = [
      Validators.required,
      ucapSameWith(this.newLoginPwFormControl)
    ];
    this.newConfirmLoginPwFormControl.setValidators(
      newConfirmLoginPwValidators
    );

    this.changePasswordForm = this.formBuilder.group({
      currentLoginPwFormControl: this.currentLoginPwFormControl,
      newLoginPwFormControl: this.newLoginPwFormControl,
      newConfirmLoginPwFormControl: this.newConfirmLoginPwFormControl
    });
  }

  onClickChangePassword() {
    this.changePassword.emit({
      currentLoginPw: PasswordUtil.encrypt(
        this.currentLoginPwFormControl.value
      ),
      newLoginPw: PasswordUtil.encrypt(this.newLoginPwFormControl.value)
    });
  }
}
