/*
 * 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(const string& in_consumerGroup) {
  consumerGroup = in_consumerGroup;
}
string LockBatchRequestBody::getClientId() {
  return clientId;
}
void LockBatchRequestBody::setClientId(const string& in_clientId) {
  clientId = in_clientId;
}
vector<MQMessageQueue> LockBatchRequestBody::getMqSet() {
  return mqSet;
}
void LockBatchRequestBody::setMqSet(const vector<MQMessageQueue>& in_mqSet) {
  mqSet = 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(const string& in_consumerGroup) {
  consumerGroup = in_consumerGroup;
}
string UnlockBatchRequestBody::getClientId() {
  return clientId;
}
void UnlockBatchRequestBody::setClientId(const string& in_clientId) {
  clientId = in_clientId;
}
vector<MQMessageQueue> UnlockBatchRequestBody::getMqSet() {
  return mqSet;
}
void UnlockBatchRequestBody::setMqSet(const vector<MQMessageQueue>& in_mqSet) {
  mqSet = 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;
}
}
