import { Injectable } from '@angular/core';
import { NatsService } from 'app/core/nats/services/nats.service';

import { Error } from 'app/modules/proto/protobuf/rpc_pb';

import {
  CheckUsernameForDuplicationRequest,
  CheckUsernameForDuplicationResponse,
  CheckNicknameForDuplicationRequest,
  CheckNicknameForDuplicationResponse,
  CaptchaRequest,
  CaptchaResponse,
  SigninRequest,
  SigninResponse,
  SigninWithoutSecurityCodeRequest,
  SigninWithoutSecurityCodeResponse,
} from 'app/modules/proto/c2se/identity_pb';
import {
  SUBJECT_CHECK_USERNAME_FOR_DUPLICATION,
  SUBJECT_CHECK_NICKNAME_FOR_DUPLICATION,
  SUBJECT_CAPTCHA,
  SUBJECT_SIGNIN,
  SUBJECT_SIGNIN_WITHOUT_SECURITY_CODE,
} from 'app/modules/proto/c2se/frontend/identity_pb';

@Injectable({
  providedIn: 'root',
})
export class IdentityService {
  /**
   * Constructor
   */
  constructor(private __natsService: NatsService) {}

  // -----------------------------------------------------------------------------------------------------
  // @ Accessors
  // -----------------------------------------------------------------------------------------------------

  // -----------------------------------------------------------------------------------------------------
  // @ Public methods
  // -----------------------------------------------------------------------------------------------------

  checkUsernameForDuplication(username: string): Promise<boolean> {
    return new Promise<boolean>((resolve, reject) => {
      let req = new CheckUsernameForDuplicationRequest();
      req.setUsername(username);

      this.__natsService
        .request<CheckUsernameForDuplicationResponse.Result>(
          SUBJECT_CHECK_USERNAME_FOR_DUPLICATION,
          req.serializeBinary(),
          CheckUsernameForDuplicationResponse.deserializeBinary
        )
        .then((result) => {
          console.log('success', result, result.getDuplicated());
          resolve(result.getDuplicated());
        })
        .catch((e: Error) => {
          console.log('failed', e);
          reject(e);
        });
    });
  }

  checkNicknameForDuplication(nickname: string): Promise<boolean> {
    return new Promise<boolean>((resolve, reject) => {
      let req = new CheckNicknameForDuplicationRequest();
      req.setNickname(nickname);

      this.__natsService
        .request<CheckNicknameForDuplicationResponse.Result>(
          SUBJECT_CHECK_NICKNAME_FOR_DUPLICATION,
          req.serializeBinary(),
          CheckNicknameForDuplicationResponse.deserializeBinary
        )
        .then((result) => {
          console.log('success', result, result.getDuplicated());
          resolve(result.getDuplicated());
        })
        .catch((e: Error) => {
          console.log('failed', e);
          reject(e);
        });
    });
  }

  captcha(): Promise<CaptchaResponse.Result> {
    return new Promise<CaptchaResponse.Result>((resolve, reject) => {
      let req = new CaptchaRequest();

      this.__natsService
        .request<CaptchaResponse.Result>(
          SUBJECT_CAPTCHA,
          req.serializeBinary(),
          CaptchaResponse.deserializeBinary
        )
        .then((result) => {
          resolve(result);
        })
        .catch((e: Error) => {
          console.log('failed', e);
          reject(e);
        });
    });
  }

  signin(
    securityCodeHash: string,
    securityCode: string,
    username: string,
    password: string
  ): Promise<SigninResponse.Result> {
    return new Promise<SigninResponse.Result>((resolve, reject) => {
      let req = new SigninRequest();
      req.setSecurityCodeHash(securityCodeHash);
      req.setSecurityCode(securityCode);
      req.setUsername(username);
      req.setPassword(password);

      this.__natsService
        .request<SigninResponse.Result>(
          SUBJECT_SIGNIN,
          req.serializeBinary(),
          SigninResponse.deserializeBinary
        )
        .then((result) => {
          resolve(result);
        })
        .catch((e: Error) => {
          console.log('failed', e);
          reject(e);
        });
    });
  }

  signinWithoutSecurityCode(
    username: string,
    password: string
  ): Promise<SigninWithoutSecurityCodeResponse.Result> {
    return new Promise<SigninWithoutSecurityCodeResponse.Result>(
      (resolve, reject) => {
        let req = new SigninWithoutSecurityCodeRequest();
        req.setUsername(username);
        req.setPassword(password);

        this.__natsService
          .request<SigninWithoutSecurityCodeResponse.Result>(
            SUBJECT_SIGNIN_WITHOUT_SECURITY_CODE,
            req.serializeBinary(),
            SigninWithoutSecurityCodeResponse.deserializeBinary
          )
          .then((result) => {
            resolve(result);
          })
          .catch((e: Error) => {
            console.log('failed', e);
            reject(e);
          });
      }
    );
  }
}
