/*
 * 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 "PullAPIWrapper.h"

#include <memory>

#include "ByteBuffer.hpp"
#include "MQClientAPIImpl.h"
#include "MQClientInstance.h"
#include "MessageAccessor.hpp"
#include "MessageDecoder.h"
#include "PullResultExt.hpp"
#include "PullSysFlag.h"

namespace rocketmq {

PullAPIWrapper::PullAPIWrapper(MQClientInstance* instance, const std::string& consumerGroup) {
  client_instance_ = instance;
  consumer_group_ = consumerGroup;
}

PullAPIWrapper::~PullAPIWrapper() {
  client_instance_ = nullptr;
  pull_from_which_node_table_.clear();
}

void PullAPIWrapper::updatePullFromWhichNode(const MQMessageQueue& mq, int brokerId) {
  std::lock_guard<std::mutex> lock(lock_);
  pull_from_which_node_table_[mq] = brokerId;
}

int PullAPIWrapper::recalculatePullFromWhichNode(const MQMessageQueue& mq) {
  std::lock_guard<std::mutex> lock(lock_);
  const auto& it = pull_from_which_node_table_.find(mq);
  if (it != pull_from_which_node_table_.end()) {
    return it->second;
  }
  return MASTER_ID;
}

std::unique_ptr<PullResult> PullAPIWrapper::processPullResult(const MQMessageQueue& mq,
                                                              std::unique_ptr<PullResult> pull_result,
                                                              SubscriptionData* subscription_data) {
  auto* pull_result_ext = dynamic_cast<PullResultExt*>(pull_result.get());
  if (pull_result_ext == nullptr) {
    return pull_result;
  }

  // update node
  updatePullFromWhichNode(mq, pull_result_ext->suggert_which_boker_id());

  std::vector<MessageExtPtr> msg_list_filter_again;
  if (FOUND == pull_result_ext->pull_status()) {
    // decode all msg list
    std::unique_ptr<ByteBuffer> byteBuffer(ByteBuffer::wrap(pull_result_ext->message_binary()));
    auto msgList = MessageDecoder::decodes(*byteBuffer);

    // filter msg list again
    if (subscription_data != nullptr && !subscription_data->tags_set().empty()) {
      msg_list_filter_again.reserve(msgList.size());
      for (const auto& msg : msgList) {
        const auto& msgTag = msg->tags();
        if (subscription_data->containsTag(msgTag)) {
          msg_list_filter_again.push_back(msg);
        }
      }
    } else {
      msg_list_filter_again.swap(msgList);
    }

    if (!msg_list_filter_again.empty()) {
      std::string min_offset = UtilAll::to_string(pull_result_ext->min_offset());
      std::string max_offset = UtilAll::to_string(pull_result_ext->max_offset());
      for (auto& msg : msg_list_filter_again) {
        const auto& tranMsg = msg->getProperty(MQMessageConst::PROPERTY_TRANSACTION_PREPARED);
        if (UtilAll::stob(tranMsg)) {
          msg->set_transaction_id(msg->getProperty(MQMessageConst::PROPERTY_UNIQ_CLIENT_MESSAGE_ID_KEYIDX));
        }
        MessageAccessor::putProperty(*msg, MQMessageConst::PROPERTY_MIN_OFFSET, min_offset);
        MessageAccessor::putProperty(*msg, MQMessageConst::PROPERTY_MAX_OFFSET, max_offset);
      }
    }
  }

  return std::unique_ptr<PullResult>(new PullResult(pull_result_ext->pull_status(),
                                                    pull_result_ext->next_begin_offset(), pull_result_ext->min_offset(),
                                                    pull_result_ext->max_offset(), std::move(msg_list_filter_again)));
}

std::unique_ptr<PullResult> PullAPIWrapper::pullKernelImpl(const MQMessageQueue& mq,
                                                           const std::string& subExpression,
                                                           const std::string& expressionType,
                                                           int64_t subVersion,
                                                           int64_t offset,
                                                           int maxNums,
                                                           int sysFlag,
                                                           int64_t commitOffset,
                                                           int brokerSuspendMaxTimeMillis,
                                                           int timeoutMillis,
                                                           CommunicationMode communicationMode,
                                                           PullCallback* pullCallback) {
  std::unique_ptr<FindBrokerResult> findBrokerResult(
      client_instance_->findBrokerAddressInSubscribe(mq.broker_name(), recalculatePullFromWhichNode(mq), false));
  if (findBrokerResult == nullptr) {
    client_instance_->updateTopicRouteInfoFromNameServer(mq.topic());
    findBrokerResult =
        client_instance_->findBrokerAddressInSubscribe(mq.broker_name(), recalculatePullFromWhichNode(mq), false);
  }

  if (findBrokerResult != nullptr) {
    int sysFlagInner = sysFlag;

    if (findBrokerResult->slave()) {
      sysFlagInner = PullSysFlag::clearCommitOffsetFlag(sysFlagInner);
    }

    PullMessageRequestHeader* pRequestHeader = new PullMessageRequestHeader();
    pRequestHeader->consumerGroup = consumer_group_;
    pRequestHeader->topic = mq.topic();
    pRequestHeader->queueId = mq.queue_id();
    pRequestHeader->queueOffset = offset;
    pRequestHeader->maxMsgNums = maxNums;
    pRequestHeader->sysFlag = sysFlagInner;
    pRequestHeader->commitOffset = commitOffset;
    pRequestHeader->suspendTimeoutMillis = brokerSuspendMaxTimeMillis;
    pRequestHeader->subscription = subExpression;
    pRequestHeader->subVersion = subVersion;

    return client_instance_->getMQClientAPIImpl()->pullMessage(findBrokerResult->broker_addr(), pRequestHeader,
                                                               timeoutMillis, communicationMode, pullCallback);
  }

  THROW_MQEXCEPTION(MQClientException, "The broker [" + mq.broker_name() + "] not exist", -1);
}

}  // namespace rocketmq
