import {
  ProtocolRequest,
  ProtocolResponse,
  ProtocolEncoder,
  PacketBody,
  ProtocolDecoder,
  ProtocolMessage,
  ProtocolStream,
  PacketBodyValue,
  ProtocolNotification,
  decodeProtocolMessage
} from '@ucap-webmessenger/protocol';
import { EventType } from '../types/event.type';
import { PushStatus } from '../types/push-status.type';
import { EventJson, decodeEventJson } from './event-json/codec';
import { Info } from '../models/info';

export interface SendRequest extends ProtocolRequest {
  // 0. 대화방SEQ(s)
  roomSeq: string;
  // 1. 이벤트타입(s)
  eventType: EventType;
  // 2. 이벤트내용(s)
  sentMessage: string;
}

export interface SendResponse extends ProtocolResponse {
  // 대화방SEQ(s)
  roomSeq: string;
  // 이벤트SEQ(n)
  seq: number;
  // 이벤트타입(s)
  eventType: EventType;
  // 발생일시(s)
  sendDate: string;
  // 이벤트내용(s)
  message: string;
  // 수신자수
  receiverCount: number;
  // 알림상태(s) PC 경우에만 관여됨 N: 푸시를 보내지 않은 이벤트 S: 푸시를 보낸 이벤트
  pushStatus: PushStatus;
  // 강퇴 타입(s)
  forcedExitType: string;
  // 요청자 이름(s)
  senderName: string;
  /** Decoded Info */
  info?: Info<EventJson>;
}

export interface SendNotification extends ProtocolNotification {
  /** 대화방SEQ(s) */
  roomSeq: string;
  /** 이벤트SEQ(n) */
  seq: number;
  /** 이벤트타입(s) */
  eventType: EventType;
  /** 발생일시(s) */
  sendDate: string;
  /** 이벤트내용(s) */
  message: string;
  /** 수신자수 */
  receiverCount: number;
  /** 알림상태(s) PC 경우에만 관여됨 N: 푸시를 보내지 않은 이벤트 S: 푸시를 보낸 이벤트 */
  pushStatus: PushStatus;
  /** 강퇴 타입(s) */
  forcedExitType: string;
  /** 요청자 이름(s) */
  senderName: string;
  /** 사용자아이디(s) */
  id?: string;
  /** 회사코드(s) */
  companyCode?: string;
  /** Decoded Info */
  info?: Info<EventJson>;
}

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

  bodyList.push(
    { type: PacketBodyValue.String, value: req.roomSeq },
    { type: PacketBodyValue.String, value: req.eventType },
    { type: PacketBodyValue.String, value: req.sentMessage }
  );

  return bodyList;
};

export const decodeSend: ProtocolDecoder<SendResponse> = (
  message: ProtocolMessage
) => {
  const seq = message.bodyList[1];
  const eventType = message.bodyList[2] as EventType;
  const sendDate = message.bodyList[3];
  const sentMessage = message.bodyList[4];
  const receiverCount = message.bodyList[5] || 0;
  const forcedExitType = message.bodyList[7];
  const senderName = message.bodyList[8];

  return decodeProtocolMessage(message, {
    roomSeq: message.bodyList[0],
    seq: message.bodyList[1],
    eventType,
    sendDate,
    message: sentMessage,
    receiverCount,
    pushStatus: message.bodyList[6] as PushStatus,
    forcedExitType,
    senderName,
    info: {
      seq,
      type: eventType,
      senderSeq: message.senderSeq,
      sendDate,
      sentMessage,
      sentMessageJson: decodeEventJson(eventType, sentMessage),
      receiverCount,
      exitForcingRequestUserName: senderName
    }
  } as SendResponse);
};

export const decodeSendNotification: ProtocolDecoder<SendNotification> = (
  message: ProtocolMessage
) => {
  const seq = message.bodyList[1];
  const eventType = message.bodyList[2] as EventType;
  const sendDate = message.bodyList[3];
  const sentMessage = message.bodyList[4];
  const receiverCount = message.bodyList[5] || 0;
  const forcedExitType = message.bodyList[7];
  const senderName = message.bodyList[8];

  return decodeProtocolMessage(message, {
    roomSeq: message.bodyList[0],
    seq,
    eventType,
    sendDate,
    message: sentMessage,
    receiverCount,
    pushStatus: message.bodyList[6] as PushStatus,
    forcedExitType,
    senderName,
    id: message.bodyList[9],
    companyCode: message.bodyList[10],
    info: {
      seq,
      type: eventType,
      senderSeq: message.senderSeq,
      sendDate,
      sentMessage,
      sentMessageJson: decodeEventJson(eventType, sentMessage),
      receiverCount,
      exitForcingRequestUserName: senderName
    }
  } as SendNotification);
};
