import {
  ProtocolRequest,
  ProtocolResponse,
  ProtocolEncoder,
  PacketBody,
  PacketBodyValue,
  ProtocolDecoder,
  ProtocolMessage,
  BodyStringDivider,
  ProtocolStream,
  decodeProtocolMessage
} from '@ucap-webmessenger/protocol';
import { LocaleCode } from '@ucap-webmessenger/core';
import { RoomType } from '../types/room.type';
import { EventType } from '@ucap-webmessenger/protocol-event';
import { EmployeeType } from '../types/employee.type';
import { RoleCode } from '@ucap-webmessenger/protocol-authentication';
import { RoomInfo } from '../models/room-info';
import { UserInfoShort } from '../models/user-info-short';
import { UserInfo } from '../models/user-info';

export interface InfoRequest extends ProtocolRequest {
  // 0. 대화방SEQ(s)
  roomSeq: string;
  // 1. 상세정보여부(y)
  isDetail: boolean;
  // 2. 언어코드(s)
  localeCode: LocaleCode;
}

export interface InfoResponse extends ProtocolResponse {
  // 0. 대화방SEQ(s)
  roomSeq: string;
}

export interface InfoData extends ProtocolStream {
  // 0. 대화방SEQ(s)
  roomSeq: string;
  // 1. {대화방정보}
  roomInfo: RoomInfo;
}

export interface UserShortData extends ProtocolStream {
  // 0. 대화방SEQ(s)
  roomSeq: string;
  // 1n. {참여자정보}
  userInfos: UserInfoShort[];
}
export interface UserData extends ProtocolStream {
  // 0. 대화방SEQ(s)
  roomSeq: string;
  // 1n. {참여자정보-D}
  userInfos: UserInfo[];
}

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

  bodyList.push({ type: PacketBodyValue.String, value: req.roomSeq });
  bodyList.push({
    type: PacketBodyValue.String,
    value: req.isDetail !== true ? 'N' : 'Y'
  }); // 요청응답을 상세로 받는것을 default
  bodyList.push({ type: PacketBodyValue.String, value: req.localeCode });

  return bodyList;
};

export const decodeInfo: ProtocolDecoder<InfoResponse> = (
  message: ProtocolMessage
) => {
  return decodeProtocolMessage(message, {
    roomSeq: message.bodyList[0]
  } as InfoResponse);
};

export const decodeInfoData: ProtocolDecoder<InfoData> = (
  message: ProtocolMessage
) => {
  let roomInfo: RoomInfo = null;
  if (message.bodyList.length > 1) {
    const info = message.bodyList[1].split(BodyStringDivider);
    if (info.length > 11) {
      roomInfo = {
        roomSeq: info[0],
        roomType: info[1] as RoomType,
        roomName: info[2],
        finalEventType: info[3] as EventType,
        finalEventMessage: info[4],
        finalEventDate: info[5],
        joinUserCount: Number(info[6]),
        noReadCnt: Number(info[7]),
        receiveAlarm: info[8] !== 'N' ? true : false,
        isJoinRoom: info[9] === 'Y' ? true : false,
        expiredFileStdSeq: Number(info[10]),
        isTimeRoom: info[11] === 'Y' ? true : false,
        timeRoomInterval: info[11] !== 'Y' ? 0 : Number(info[12]) || 0
      };
    }
  }

  return decodeProtocolMessage(message, {
    roomSeq: message.bodyList[0],
    roomInfo
  } as InfoData);
};

export const decodeUserShortData: ProtocolDecoder<UserShortData> = (
  message: ProtocolMessage
) => {
  const userInfos: UserInfoShort[] = [];
  message.bodyList.slice(1).forEach(userInfo => {
    const info = userInfo.split(BodyStringDivider);
    userInfos.push({
      seq: Number(info[0]),
      name: info[1],
      profileImageFile: info[2],
      isJoinRoom: info[3] === 'Y' ? true : false,
      lastReadEventSeq: Number(info[4]),
      madn: info[5],
      hardSadn: info[6],
      fmcSadn: info[7],
      nameEn: info[8],
      nameCn: info[9],
      isPrivacyAgree: info[10] === 'Y' ? true : false,
      isValidLogin: info[11] === 'Y' ? true : false,
      employeeType: info[12] as EmployeeType,
      fontColor: info[13]
    });
  });

  return decodeProtocolMessage(message, {
    roomSeq: message.bodyList[0],
    userInfos
  } as UserShortData);
};

export const decodeUserData: ProtocolDecoder<UserData> = (
  message: ProtocolMessage
) => {
  const userInfos: UserInfo[] = [];
  message.bodyList.slice(1).forEach(userInfo => {
    const info = userInfo.split(BodyStringDivider);
    userInfos.push({
      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],
      isJoinRoom: info[11] === 'Y' ? true : false,
      lastReadEventSeq: info[12],
      isActive: info[13] === 'Y' ? true : false,
      roleCd: info[14] as RoleCode,
      employeeNum: info[15],
      madn: info[16],
      hardSadn: info[17],
      fmcSadn: info[18],
      nameEn: info[19],
      nameCn: info[20],
      gradeEn: info[21],
      gradeCn: info[22],
      deptNameEn: info[23],
      deptNameCn: info[24],
      callMode: info[25],
      isPrivacyAgree: info[26] === 'Y' ? true : false,
      isValidLogin: info[27] === 'Y' ? true : false,
      employeeType: info[28] as EmployeeType,
      id: info[29]
    });
  });

  return decodeProtocolMessage(message, {
    roomSeq: message.bodyList[0],
    userInfos
  } as UserData);
};

export interface UserStatusOfflineRequest extends ProtocolRequest {
  // 대화방SEQ(s)
  roomSeq: string;
}

export interface UserStatusOfflineResponse extends ProtocolResponse {
  // 대화방SEQ(s)
  roomSeq: string;
  // 사용자SEQ(n)...
  userSeqs: number[];
}
export const encodeUserStatusOffline: ProtocolEncoder<UserStatusOfflineRequest> = (
  req: UserStatusOfflineRequest
) => {
  const bodyList: PacketBody[] = [];

  bodyList.push({ type: PacketBodyValue.String, value: req.roomSeq });
  return bodyList;
};
export const decodeUserStatusOffline: ProtocolDecoder<UserStatusOfflineResponse> = (
  message: ProtocolMessage
) => {
  let userSeqs: number[] = [];
  if (message.bodyList.length > 1) {
    userSeqs = message.bodyList.slice(1);
  }
  return decodeProtocolMessage(message, {
    roomSeq: message.bodyList[0],
    userSeqs
  } as UserStatusOfflineResponse);
};