/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "MQDecoder.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sstream>
#include "Logging.h"
#include "MemoryOutputStream.h"
#include "MessageSysFlag.h"
#include "UtilAll.h"

namespace rocketmq {

//<!***************************************************************************
const int MQDecoder::MSG_ID_LENGTH = 8 + 8;

const char MQDecoder::NAME_VALUE_SEPARATOR = 1;
const char MQDecoder::PROPERTY_SEPARATOR = 2;

int MQDecoder::MessageMagicCodePostion = 4;
int MQDecoder::MessageFlagPostion = 16;
int MQDecoder::MessagePhysicOffsetPostion = 28;
int MQDecoder::MessageStoreTimestampPostion = 56;

//<!***************************************************************************
string MQDecoder::createMessageId(sockaddr addr, int64 offset) {
  int host, port;
  socketAddress2IPPort(addr, host, port);

  MemoryOutputStream outputmen(MSG_ID_LENGTH);
  outputmen.writeIntBigEndian(host);
  outputmen.writeIntBigEndian(port);
  outputmen.writeInt64BigEndian(offset);

  const char* bytes = static_cast<const char*>(outputmen.getData());
  int len = outputmen.getDataSize();

  return UtilAll::bytes2string(bytes, len);
}

MQMessageId MQDecoder::decodeMessageId(const string& msgId) {
  string ipStr = msgId.substr(0, 8);
  string portStr = msgId.substr(8, 8);
  string offsetStr = msgId.substr(16, 16);

  int num = strspn(offsetStr.c_str(), "F");
  offsetStr = offsetStr.substr(num, 16 - num);

  char* end;
  int ipInt = strtoul(ipStr.c_str(), &end, 16);
  int portInt = strtoul(portStr.c_str(), &end, 16);
  uint64 offset = strtoul(offsetStr.c_str(), &end, 16);
  // int64 offset = UtilAll::hexstr2ull(offsetStr.c_str());

  struct sockaddr_in sa;
  sa.sin_family = AF_INET;
  sa.sin_port = htons(portInt);
  sa.sin_addr.s_addr = htonl(ipInt);
  sockaddr addr;
  memcpy(&addr, &sa, sizeof(sockaddr));

  MQMessageId id(addr, offset);
  return id;
}

MQMessageExt* MQDecoder::decode(MemoryInputStream& byteBuffer) {
  return decode(byteBuffer, true);
}

MQMessageExt* MQDecoder::decode(MemoryInputStream& byteBuffer, bool readBody) {
  MQMessageExt* msgExt = new MQMessageExt();

  // 1 TOTALSIZE
  int storeSize = byteBuffer.readIntBigEndian();
  msgExt->setStoreSize(storeSize);

  // 2 MAGICCODE sizeof(int)
  byteBuffer.skipNextBytes(sizeof(int));

  // 3 BODYCRC
  int bodyCRC = byteBuffer.readIntBigEndian();
  msgExt->setBodyCRC(bodyCRC);

  // 4 QUEUEID
  int queueId = byteBuffer.readIntBigEndian();
  msgExt->setQueueId(queueId);

  // 5 FLAG
  int flag = byteBuffer.readIntBigEndian();
  msgExt->setFlag(flag);

  // 6 QUEUEOFFSET
  int64 queueOffset = byteBuffer.readInt64BigEndian();
  msgExt->setQueueOffset(queueOffset);

  // 7 PHYSICALOFFSET
  int64 physicOffset = byteBuffer.readInt64BigEndian();
  msgExt->setCommitLogOffset(physicOffset);

  // 8 SYSFLAG
  int sysFlag = byteBuffer.readIntBigEndian();
  msgExt->setSysFlag(sysFlag);

  // 9 BORNTIMESTAMP
  int64 bornTimeStamp = byteBuffer.readInt64BigEndian();
  msgExt->setBornTimestamp(bornTimeStamp);

  // 10 BORNHOST
  int bornHost = byteBuffer.readIntBigEndian();
  int port = byteBuffer.readIntBigEndian();
  sockaddr bornAddr = IPPort2socketAddress(bornHost, port);
  msgExt->setBornHost(bornAddr);

  // 11 STORETIMESTAMP
  int64 storeTimestamp = byteBuffer.readInt64BigEndian();
  msgExt->setStoreTimestamp(storeTimestamp);

  // // 12 STOREHOST
  int storeHost = byteBuffer.readIntBigEndian();
  port = byteBuffer.readIntBigEndian();
  sockaddr storeAddr = IPPort2socketAddress(storeHost, port);
  msgExt->setStoreHost(storeAddr);

  // 13 RECONSUMETIMES
  int reconsumeTimes = byteBuffer.readIntBigEndian();
  msgExt->setReconsumeTimes(reconsumeTimes);

  // 14 Prepared Transaction Offset
  int64 preparedTransactionOffset = byteBuffer.readInt64BigEndian();
  msgExt->setPreparedTransactionOffset(preparedTransactionOffset);

  // 15 BODY
  int bodyLen = byteBuffer.readIntBigEndian();
  if (bodyLen > 0) {
    if (readBody) {
      MemoryBlock block;
      byteBuffer.readIntoMemoryBlock(block, bodyLen);

      const char* const pBody = static_cast<const char*>(block.getData());
      int len = block.getSize();
      string msgbody(pBody, len);

      // decompress body
      if ((sysFlag & MessageSysFlag::CompressedFlag) == MessageSysFlag::CompressedFlag) {
        string outbody;
        if (UtilAll::inflate(msgbody, outbody)) {
          msgExt->setBody(outbody);
        }
      } else {
        msgExt->setBody(msgbody);
      }
    } else {
      byteBuffer.skipNextBytes(bodyLen);
    }
  }

  // 16 TOPIC
  int topicLen = (int)byteBuffer.readByte();
  MemoryBlock block;
  byteBuffer.readIntoMemoryBlock(block, topicLen);
  const char* const pTopic = static_cast<const char*>(block.getData());
  topicLen = block.getSize();
  msgExt->setTopic(pTopic, topicLen);

  // 17 properties
  short propertiesLen = byteBuffer.readShortBigEndian();
  if (propertiesLen > 0) {
    MemoryBlock block;
    byteBuffer.readIntoMemoryBlock(block, propertiesLen);
    const char* const pProperty = static_cast<const char*>(block.getData());
    int len = block.getSize();
    string propertiesString(pProperty, len);

    map<string, string> propertiesMap;
    string2messageProperties(propertiesString, propertiesMap);
    msgExt->setPropertiesInternal(propertiesMap);
    propertiesMap.clear();
  }

  // 18 msg ID
  string offsetMsgId = createMessageId(msgExt->getStoreHost(), (int64)msgExt->getCommitLogOffset());
  msgExt->setOffsetMsgId(offsetMsgId);

  string msgId = msgExt->getProperty(MQMessage::PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX);
  if (msgId.empty()) {
    msgId = offsetMsgId;
  }
  msgExt->setMsgId(msgId);

  // LOG_INFO("get msgExt from remote server, its contents are:%s", msgExt->toString().c_str());
  return msgExt;
}

void MQDecoder::decodes(const MemoryBlock* mem, vector<MQMessageExt>& mqvec) {
  mqvec.clear();
  decodes(mem, mqvec, true);
}

void MQDecoder::decodes(const MemoryBlock* mem, vector<MQMessageExt>& mqvec, bool readBody) {
  MemoryInputStream rawInput(*mem, true);

  while (rawInput.getNumBytesRemaining() > 0) {
    unique_ptr<MQMessageExt> msg(decode(rawInput, readBody));
    mqvec.push_back(*msg);
  }
}

string MQDecoder::messageProperties2String(const map<string, string>& properties) {
  string os;

  for (const auto& it : properties) {
    // os << it->first << NAME_VALUE_SEPARATOR << it->second << PROPERTY_SEPARATOR;
    os.append(it.first);
    os += NAME_VALUE_SEPARATOR;
    os.append(it.second);
    os += PROPERTY_SEPARATOR;
  }

  return os;
}

void MQDecoder::string2messageProperties(const string& propertiesString, map<string, string>& properties) {
  vector<string> out;
  UtilAll::Split(out, propertiesString, PROPERTY_SEPARATOR);

  for (size_t i = 0; i < out.size(); i++) {
    vector<string> outValue;
    UtilAll::Split(outValue, out[i], NAME_VALUE_SEPARATOR);

    if (outValue.size() == 2) {
      properties[outValue[0]] = outValue[1];
    }
  }
}
}  // namespace rocketmq
