/*
 * 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 "LockBatchBody.h"
#include "Logging.h"
namespace rocketmq {  //<!end namespace;

string LockBatchRequestBody::getConsumerGroup() {
  return consumerGroup;
}
void LockBatchRequestBody::setConsumerGroup(string in_consumerGroup) {
  consumerGroup = in_consumerGroup;
}
string LockBatchRequestBody::getClientId() {
  return clientId;
}
void LockBatchRequestBody::setClientId(string in_clientId) {
  clientId = in_clientId;
}
vector<MQMessageQueue> LockBatchRequestBody::getMqSet() {
  return mqSet;
}
void LockBatchRequestBody::setMqSet(vector<MQMessageQueue> in_mqSet) {
  mqSet.swap(in_mqSet);
}
void LockBatchRequestBody::Encode(string& outData) {
  Json::Value root;
  root["consumerGroup"] = consumerGroup;
  root["clientId"] = clientId;

  vector<MQMessageQueue>::const_iterator it = mqSet.begin();
  for (; it != mqSet.end(); it++) {
    root["mqSet"].append(toJson(*it));
  }

  Json::FastWriter fastwrite;
  outData = fastwrite.write(root);
}

Json::Value LockBatchRequestBody::toJson(const MQMessageQueue& mq) const {
  Json::Value outJson;
  outJson["topic"] = mq.getTopic();
  outJson["brokerName"] = mq.getBrokerName();
  outJson["queueId"] = mq.getQueueId();
  return outJson;
}

vector<MQMessageQueue> LockBatchResponseBody::getLockOKMQSet() {
  return lockOKMQSet;
}
void LockBatchResponseBody::setLockOKMQSet(vector<MQMessageQueue> in_lockOKMQSet) {
  lockOKMQSet.swap(in_lockOKMQSet);
}

void LockBatchResponseBody::Decode(const MemoryBlock* mem, vector<MQMessageQueue>& messageQueues) {
  messageQueues.clear();
  //<! decode;
  const std::string pData(mem->getData(), mem->getSize());

  Json::Reader reader;
  Json::Value root;
  if (!reader.parse(pData, root)) {
    LOG_WARN("decode LockBatchResponseBody error");
    return;
  }

  Json::Value mqs = root["lockOKMQSet"];
  LOG_DEBUG("LockBatchResponseBody mqs size:%d", mqs.size());
  for (unsigned int i = 0; i < mqs.size(); i++) {
    MQMessageQueue mq;
    Json::Value qd = mqs[i];
    mq.setTopic(qd["topic"].asString());
    mq.setBrokerName(qd["brokerName"].asString());
    mq.setQueueId(qd["queueId"].asInt());
    LOG_INFO("LockBatchResponseBody MQ:%s", mq.toString().c_str());
    messageQueues.push_back(mq);
  }
}

string UnlockBatchRequestBody::getConsumerGroup() {
  return consumerGroup;
}
void UnlockBatchRequestBody::setConsumerGroup(string in_consumerGroup) {
  consumerGroup = in_consumerGroup;
}
string UnlockBatchRequestBody::getClientId() {
  return clientId;
}
void UnlockBatchRequestBody::setClientId(string in_clientId) {
  clientId = in_clientId;
}
vector<MQMessageQueue> UnlockBatchRequestBody::getMqSet() {
  return mqSet;
}
void UnlockBatchRequestBody::setMqSet(vector<MQMessageQueue> in_mqSet) {
  mqSet.swap(in_mqSet);
}
void UnlockBatchRequestBody::Encode(string& outData) {
  Json::Value root;
  root["consumerGroup"] = consumerGroup;
  root["clientId"] = clientId;

  vector<MQMessageQueue>::const_iterator it = mqSet.begin();
  for (; it != mqSet.end(); it++) {
    root["mqSet"].append(toJson(*it));
  }

  Json::FastWriter fastwrite;
  outData = fastwrite.write(root);
}

Json::Value UnlockBatchRequestBody::toJson(const MQMessageQueue& mq) const {
  Json::Value outJson;
  outJson["topic"] = mq.getTopic();
  outJson["brokerName"] = mq.getBrokerName();
  outJson["queueId"] = mq.getQueueId();
  return outJson;
}
}
