import { DeviceType, LocaleCode } from '@ucap-webmessenger/core';
import {
  ProtocolRequest,
  ProtocolResponse,
  ProtocolEncoder,
  PacketBody,
  PacketBodyValue,
  ProtocolDecoder,
  ProtocolMessage,
  BodyStringDivider,
  decodeProtocolMessage
} from '@ucap-webmessenger/protocol';
import { SSOMode } from '../types/sso-mode';
import { RoleCode } from '../types/role-code';
import { UserInfo } from '../models/user-info';
import { EmployeeType } from '@ucap-webmessenger/protocol-room';

export interface LoginRequest extends ProtocolRequest {
  // 0. LoginID(s)
  loginId: string;
  // 1. LoginPW(e)
  loginPw: string;
  // 2. 단말타입(s) (WEB)
  deviceType: DeviceType;
  // 3. 디바이스ID(s) (for mobile)
  deviceId: string;
  // 4. Token(n)
  token: string;
  // 5. 언어코드(s)
  localeCode: LocaleCode;
  // 6. Push ID (for mobile)
  pushId: string;
  // 7. 기관코드(s)
  companyCode: string;
  // 8. PW_ENC_T
  passwordEncodingType: number;
  // 9. Client버전(s)
  clientVersion: string;
  // 10. 재연결여부(s)
  reconnect: boolean;
  // 11. IP(s)
  ip: string;
  // 12. 호스트명(s)
  hostName: string;
  // 13. SSO모드(SSO_NONE=0:사용안함, SSO_AUTH=1:사용, SSO_AUTO=2:자동실행, SSO_VALI=3:세션연장)
  ssoMode: SSOMode;
  // 14. 사용자고유정보(s)
  userSpecificInformation: string;
  // 15. 안드로이드 ID(s)
  andId: string;
  // 16. push_ID 갱신여부(s)
  andPushRefreshYn: string;
}

export interface LoginResponse extends ProtocolResponse {
  loginId: string;
  userSeq: number;
  userInfo: UserInfo;
  token: number;
  companyCode: string;
  departmentCode: number;
  userId: string;
  passwordEncodingType: number;
  encriptionKey: string;
  existingPid: boolean;
  roleCode: RoleCode;
  statusMessage1: string;
  statusMessage2: string;
  statusMessage3: string;
  fileDownloadAllow: boolean;
  fileRetentionPeriod: number;
  passwordValidityPeriod: number;
  privateInformationAgree: boolean;
  madn: string;
  hardPhoneSadn: string;
  fmcSadn: string;
  pbxIndex: number;
  /** PW 유효 여부(s) | Y : 유효함 N : 만료됨 */
  passwordValid: boolean;
  validAccount: boolean;
  validDevice: boolean;
  useableDevice: boolean;
  deviceScreenForcedLock: boolean;
  tokenString: string;
  havePermissionsForIntegratedMessageBox: boolean;
  talkWithMeBotSeq: number;
  pinCode: string;
  permissionsForViewSchedule: string;
  havePermissionsForDevice: boolean;
}

const decodeUserInfo = (encodedValue: string) => {
  const info = encodedValue.split(BodyStringDivider);

  return {
    seq: Number(info[0]),
    name: info[1],
    profileImageFile: info[2],
    grade: info[3],
    intro: info[4],
    companyCode: info[5],
    hpNumber: info[6],
    lineNumber: info[7],
    email: info[8],
    isMobile: info[9] === 'Y' ? true : false,
    deptName: info[10],
    selectOrder: Number(info[11]),
    isActive: info[12] === 'Y' ? true : false,
    roleCd: Number(info[13]) as RoleCode,
    employeeNum: info[14],
    nameEn: info[15],
    nameCn: info[16],
    gradeEn: info[17],
    gradeCn: info[18],
    deptNameEn: info[19],
    deptNameCn: info[20],
    employeeType: info[21] as EmployeeType,
    inDomestic: info[22] === 'Y' ? true : false
  } as UserInfo;
};

export const encodeLogin: ProtocolEncoder<LoginRequest> = (
  req: LoginRequest
) => {
  const bodyList: PacketBody[] = [];

  bodyList.push(
    { type: PacketBodyValue.String, value: req.loginId },
    { type: PacketBodyValue.String, value: req.loginPw },
    { type: PacketBodyValue.String, value: req.deviceType },
    { type: PacketBodyValue.String, value: req.deviceId },
    { type: PacketBodyValue.String, value: req.token },
    { type: PacketBodyValue.String, value: req.localeCode },
    { type: PacketBodyValue.String, value: req.pushId }, // 6

    { type: PacketBodyValue.String, value: req.companyCode },
    { type: PacketBodyValue.Integer, value: req.passwordEncodingType },
    { type: PacketBodyValue.String, value: req.clientVersion },
    { type: PacketBodyValue.String, value: req.reconnect ? 'Y' : 'N' },
    { type: PacketBodyValue.String, value: req.ip },
    { type: PacketBodyValue.String, value: req.hostName },
    { type: PacketBodyValue.String, value: '' }, // 13

    { type: PacketBodyValue.String, value: req.userSpecificInformation },
    { type: PacketBodyValue.String, value: req.andId },
    { type: PacketBodyValue.String, value: req.andPushRefreshYn }
  );

  return bodyList;
};

export const decodeLogin: ProtocolDecoder<LoginResponse> = (
  message: ProtocolMessage
) => {
  return decodeProtocolMessage(message, {
    loginId: message.bodyList[0],
    userSeq: message.bodyList[1],
    userInfo: decodeUserInfo(message.bodyList[2]),
    token: message.bodyList[3],
    companyCode: message.bodyList[4],
    departmentCode: message.bodyList[5],
    userId: message.bodyList[6],
    passwordEncodingType: message.bodyList[7],
    encriptionKey: message.bodyList[8],
    existingPid: message.bodyList[9] === 'Y' ? true : false,
    roleCode: message.bodyList[10] as RoleCode,
    statusMessage1: message.bodyList[11],
    statusMessage2: message.bodyList[12],
    statusMessage3: message.bodyList[13],
    fileDownloadAllow: message.bodyList[14] === 'Y' ? true : false,
    fileRetentionPeriod: message.bodyList[15],
    passwordValidityPeriod: message.bodyList[16],
    privateInformationAgree: message.bodyList[17] === 'Y' ? true : false,
    madn: message.bodyList[18],
    hardPhoneSadn: message.bodyList[19],
    fmcSadn: message.bodyList[20],
    pbxIndex: message.bodyList[21],
    passwordValid: message.bodyList[22] === 'Y' ? true : false,
    validAccount: message.bodyList[23] === 'Y' ? true : false,
    validDevice: message.bodyList[24] === 'Y' ? true : false,
    useableDevice: message.bodyList[25] === 'Y' ? true : false,
    deviceScreenForcedLock: message.bodyList[26] === 'Y' ? true : false,
    tokenString: message.bodyList[27],
    havePermissionsForIntegratedMessageBox:
      message.bodyList[28] === 'Y' ? true : false,
    talkWithMeBotSeq: message.bodyList[29],
    pinCode: message.bodyList[30],
    permissionsForViewSchedule: message.bodyList[31],
    havePermissionsForDevice: message.bodyList[32] === 'Y' ? true : false
  } as LoginResponse);
};
