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

#ifndef WIN32
#include <signal.h>
#endif

#include "AssignedMessageQueue.hpp"
#include "FilterAPI.hpp"
#include "LocalFileOffsetStore.h"
#include "MQAdminImpl.h"
#include "MQClientAPIImpl.h"
#include "MQClientInstance.h"
#include "NamespaceUtil.h"
#include "PullAPIWrapper.h"
#include "PullSysFlag.h"
#include "RebalanceLitePullImpl.h"
#include "RemoteBrokerOffsetStore.h"
#include "UtilAll.h"
#include "Validators.h"

static const long PULL_TIME_DELAY_MILLS_WHEN_PAUSE = 1000;
static const long PULL_TIME_DELAY_MILLS_WHEN_FLOW_CONTROL = 50;

namespace rocketmq {

class DefaultLitePullConsumerImpl::MessageQueueListenerImpl : public MessageQueueListener {
 public:
  MessageQueueListenerImpl(DefaultLitePullConsumerImplPtr pull_consumer) : default_lite_pull_consumer_(pull_consumer) {}

  ~MessageQueueListenerImpl() = default;

  void messageQueueChanged(const std::string& topic,
                           std::vector<MQMessageQueue>& mq_all,
                           std::vector<MQMessageQueue>& mq_divided) override {
    auto consumer = default_lite_pull_consumer_.lock();
    if (nullptr == consumer) {
      return;
    }
    switch (consumer->messageModel()) {
      case BROADCASTING:
        consumer->updateAssignedMessageQueue(topic, mq_all);
        consumer->updatePullTask(topic, mq_all);
        break;
      case CLUSTERING:
        consumer->updateAssignedMessageQueue(topic, mq_divided);
        consumer->updatePullTask(topic, mq_divided);
        break;
      default:
        break;
    }
  }

 private:
  std::weak_ptr<DefaultLitePullConsumerImpl> default_lite_pull_consumer_;
};

class DefaultLitePullConsumerImpl::ConsumeRequest {
 public:
  ConsumeRequest(std::vector<MessageExtPtr>&& message_exts,
                 const MQMessageQueue& message_queue,
                 ProcessQueuePtr process_queue)
      : message_exts_(std::move(message_exts)), message_queue_(message_queue), process_queue_(process_queue) {}

 public:
  std::vector<MessageExtPtr>& message_exts() { return message_exts_; }

  MQMessageQueue& message_queue() { return message_queue_; }

  ProcessQueuePtr process_queue() { return process_queue_; }

 private:
  std::vector<MessageExtPtr> message_exts_;
  MQMessageQueue message_queue_;
  ProcessQueuePtr process_queue_;
};

class DefaultLitePullConsumerImpl::PullTaskImpl : public std::enable_shared_from_this<PullTaskImpl> {
 public:
  PullTaskImpl(DefaultLitePullConsumerImplPtr pull_consumer, const MQMessageQueue& message_queue)
      : default_lite_pull_consumer_(pull_consumer), message_queue_(message_queue), cancelled_(false) {}

  void run() {
    auto consumer = default_lite_pull_consumer_.lock();
    if (nullptr == consumer) {
      LOG_WARN_NEW("PullTaskImpl::run: DefaultLitePullConsumerImpl is released.");
      return;
    }

    if (cancelled_) {
      return;
    }

    if (consumer->assigned_message_queue_->isPaused(message_queue_)) {
      consumer->scheduled_thread_pool_executor_.schedule(
          std::bind(&DefaultLitePullConsumerImpl::PullTaskImpl::run, shared_from_this()),
          PULL_TIME_DELAY_MILLS_WHEN_PAUSE, time_unit::milliseconds);
      LOG_DEBUG_NEW("Message Queue: {} has been paused!", message_queue_.toString());
      return;
    }

    auto process_queue = consumer->assigned_message_queue_->getProcessQueue(message_queue_);
    if (nullptr == process_queue || process_queue->dropped()) {
      LOG_INFO_NEW("The message queue not be able to poll, because it's dropped. group={}, messageQueue={}",
                   consumer->groupName(), message_queue_.toString());
      return;
    }

    auto config = consumer->getDefaultLitePullConsumerConfig();

    if (consumer->consume_request_cache_.size() * config->pull_batch_size() > config->pull_threshold_for_all()) {
      consumer->scheduled_thread_pool_executor_.schedule(
          std::bind(&DefaultLitePullConsumerImpl::PullTaskImpl::run, shared_from_this()),
          PULL_TIME_DELAY_MILLS_WHEN_FLOW_CONTROL, time_unit::milliseconds);
      if ((consumer->consume_request_flow_control_times_++ % 1000) == 0)
        LOG_WARN_NEW(
            "The consume request count exceeds threshold {}, so do flow control, consume request count={}, "
            "flowControlTimes={}",
            config->pull_threshold_for_all(), consumer->consume_request_cache_.size(),
            consumer->consume_request_flow_control_times_);
      return;
    }

    auto cached_message_count = process_queue->getCacheMsgCount();
    if (cached_message_count > config->pull_threshold_for_queue()) {
      consumer->scheduled_thread_pool_executor_.schedule(
          std::bind(&DefaultLitePullConsumerImpl::PullTaskImpl::run, shared_from_this()),
          PULL_TIME_DELAY_MILLS_WHEN_FLOW_CONTROL, time_unit::milliseconds);
      if ((consumer->queue_flow_control_times_++ % 1000) == 0) {
        LOG_WARN_NEW(
            "The cached message count exceeds the threshold {}, so do flow control, minOffset={}, maxOffset={}, "
            "count={}, size={} MiB, flowControlTimes={}",
            config->pull_threshold_for_queue(), process_queue->getCacheMinOffset(), process_queue->getCacheMaxOffset(),
            cached_message_count, "unknown", consumer->queue_flow_control_times_);
      }
      return;
    }

    // long cachedMessageSizeInMiB = processQueue->getMsgSize() / (1024 * 1024);
    // if (cachedMessageSizeInMiB > consumer.getPullThresholdSizeForQueue()) {
    //   scheduledThreadPoolExecutor.schedule(this, PULL_TIME_DELAY_MILLS_WHEN_FLOW_CONTROL, TimeUnit.MILLISECONDS);
    //   if ((queueFlowControlTimes++ % 1000) == 0) {
    //     log.warn(
    //         "The cached message size exceeds the threshold {} MiB, so do flow control, minOffset={}, maxOffset={},
    //         "
    //         "count={}, size={} MiB, flowControlTimes={}",
    //         consumer.getPullThresholdSizeForQueue(), processQueue.getMsgTreeMap().firstKey(),
    //         processQueue.getMsgTreeMap().lastKey(), cachedMessageCount, cachedMessageSizeInMiB,
    //         queueFlowControlTimes);
    //   }
    //   return;
    // }

    // if (processQueue.getMaxSpan() > consumer.getConsumeMaxSpan()) {
    //   scheduledThreadPoolExecutor.schedule(this, PULL_TIME_DELAY_MILLS_WHEN_FLOW_CONTROL, TimeUnit.MILLISECONDS);
    //   if ((queueMaxSpanFlowControlTimes++ % 1000) == 0) {
    //     log.warn(
    //         "The queue's messages, span too long, so do flow control, minOffset={}, maxOffset={}, maxSpan={}, "
    //         "flowControlTimes={}",
    //         processQueue.getMsgTreeMap().firstKey(), processQueue.getMsgTreeMap().lastKey(),
    //         processQueue.getMaxSpan(),
    //         queueMaxSpanFlowControlTimes);
    //   }
    //   return;
    // }

    auto offset = consumer->nextPullOffset(message_queue_);
    long pull_delay_time_millis = 0;
    SubscriptionData* subscription_data = nullptr;
    try {
      if (consumer->subscription_type_ == SubscriptionType::SUBSCRIBE) {
        subscription_data = consumer->rebalance_impl_->getSubscriptionData(message_queue_.topic());
      } else {
        subscription_data = FilterAPI::buildSubscriptionData(message_queue_.topic(), SUB_ALL).release();
      }

      std::unique_ptr<PullResult> pull_result(
          consumer->pull(message_queue_, subscription_data, offset, config->pull_batch_size()));

      switch (pull_result->pull_status()) {
        case PullStatus::FOUND: {
          auto objLock = consumer->message_queue_lock_.fetchLockObject(message_queue_);
          std::lock_guard<std::mutex> lock(*objLock);
          if (!pull_result->msg_found_list().empty() &&
              consumer->assigned_message_queue_->getSeekOffset(message_queue_) == -1) {
            process_queue->putMessage(pull_result->msg_found_list());
            consumer->submitConsumeRequest(
                new ConsumeRequest(std::move(pull_result->msg_found_list()), message_queue_, process_queue));
          }
        } break;
        case PullStatus::OFFSET_ILLEGAL:
          LOG_WARN_NEW("The pull request offset illegal, {}", pull_result->toString());
          break;
        case PullStatus::NO_NEW_MSG:
        case PullStatus::NO_MATCHED_MSG:
          pull_delay_time_millis = 1000;
          break;
        case PullStatus::NO_LATEST_MSG:
          pull_delay_time_millis = config->pull_time_delay_millis_when_exception();
          break;
        default:
          break;
      }

      consumer->updatePullOffset(message_queue_, pull_result->next_begin_offset());
    } catch (std::exception& e) {
      pull_delay_time_millis = config->pull_time_delay_millis_when_exception();
      LOG_ERROR_NEW("An error occurred in pull message process. {}", e.what());
    }

    if (consumer->subscription_type_ != SubscriptionType::SUBSCRIBE) {
      delete subscription_data;
    }

    if (!cancelled_) {
      consumer->scheduled_thread_pool_executor_.schedule(
          std::bind(&DefaultLitePullConsumerImpl::PullTaskImpl::run, shared_from_this()), pull_delay_time_millis,
          time_unit::milliseconds);
    } else {
      LOG_WARN_NEW("The Pull Task is cancelled after doPullTask, {}", message_queue_.toString());
    }
  }

 public:
  inline const MQMessageQueue& message_queue() { return message_queue_; }

  inline bool is_cancelled() const { return cancelled_; }
  inline void set_cancelled(bool cancelled) { cancelled_ = cancelled; }

 private:
  std::weak_ptr<DefaultLitePullConsumerImpl> default_lite_pull_consumer_;
  MQMessageQueue message_queue_;
  volatile bool cancelled_;
};

DefaultLitePullConsumerImpl::DefaultLitePullConsumerImpl(DefaultLitePullConsumerConfigPtr config)
    : DefaultLitePullConsumerImpl(config, nullptr) {}

DefaultLitePullConsumerImpl::DefaultLitePullConsumerImpl(DefaultLitePullConsumerConfigPtr config, RPCHookPtr rpcHook)
    : MQClientImpl(config, rpcHook),
      start_time_(UtilAll::currentTimeMillis()),
      subscription_type_(SubscriptionType::NONE),
      consume_request_flow_control_times_(0),
      queue_flow_control_times_(0),
      next_auto_commit_deadline_(-1LL),
      auto_commit_(true),
      message_queue_listener_(nullptr),
      assigned_message_queue_(new AssignedMessageQueue()),
      scheduled_thread_pool_executor_("PullMsgThread", config->pull_thread_nums(), false),
      scheduled_executor_service_("MonitorMessageQueueChangeThread", false),
      rebalance_impl_(new RebalanceLitePullImpl(this)),
      pull_api_wrapper_(nullptr),
      offset_store_(nullptr) {}

DefaultLitePullConsumerImpl::~DefaultLitePullConsumerImpl() = default;

void DefaultLitePullConsumerImpl::start() {
#ifndef WIN32
  /* Ignore the SIGPIPE */
  struct sigaction sa;
  memset(&sa, 0, sizeof(struct sigaction));
  sa.sa_handler = SIG_IGN;
  sa.sa_flags = 0;
  ::sigaction(SIGPIPE, &sa, 0);
#endif

  switch (service_state_) {
    case CREATE_JUST: {
      // wrap namespace
      client_config_->set_group_name(
          NamespaceUtil::wrapNamespace(client_config_->name_space(), client_config_->group_name()));

      LOG_INFO_NEW("the consumer [{}] start beginning.", client_config_->group_name());

      service_state_ = START_FAILED;

      checkConfig();

      if (messageModel() == MessageModel::CLUSTERING) {
        client_config_->changeInstanceNameToPID();
      }

      // init client_instance_
      MQClientImpl::start();

      // init rebalance_impl_
      rebalance_impl_->set_consumer_group(client_config_->group_name());
      rebalance_impl_->set_message_model(getDefaultLitePullConsumerConfig()->message_model());
      rebalance_impl_->set_allocate_mq_strategy(getDefaultLitePullConsumerConfig()->allocate_mq_strategy());
      rebalance_impl_->set_client_instance(client_instance_.get());

      // init pull_api_wrapper_
      pull_api_wrapper_.reset(new PullAPIWrapper(client_instance_.get(), client_config_->group_name()));
      // TODO: registerFilterMessageHook

      // init offset_store_
      switch (getDefaultLitePullConsumerConfig()->message_model()) {
        case MessageModel::BROADCASTING:
          offset_store_.reset(new LocalFileOffsetStore(client_instance_.get(), client_config_->group_name()));
          break;
        case MessageModel::CLUSTERING:
          offset_store_.reset(new RemoteBrokerOffsetStore(client_instance_.get(), client_config_->group_name()));
          break;
      }
      offset_store_->load();

      scheduled_thread_pool_executor_.set_thread_nums(getDefaultLitePullConsumerConfig()->pull_thread_nums());
      scheduled_thread_pool_executor_.startup();
      scheduled_executor_service_.startup();

      // register consumer
      bool registerOK = client_instance_->registerConsumer(client_config_->group_name(), this);
      if (!registerOK) {
        service_state_ = CREATE_JUST;
        THROW_MQEXCEPTION(MQClientException, "The cousumer group[" + client_config_->group_name() +
                                                 "] has been created before, specify another name please.",
                          -1);
      }

      client_instance_->start();

      startScheduleTask();

      LOG_INFO_NEW("the consumer [{}] start OK", client_config_->group_name());
      service_state_ = RUNNING;

      operateAfterRunning();
      break;
    }
    case RUNNING:
    case START_FAILED:
    case SHUTDOWN_ALREADY:
      THROW_MQEXCEPTION(MQClientException, "The PullConsumer service state not OK, maybe started once", -1);
      break;
    default:
      break;
  };
}

void DefaultLitePullConsumerImpl::checkConfig() {
  const auto& groupname = client_config_->group_name();

  // check consumerGroup
  Validators::checkGroup(groupname);

  // consumerGroup
  if (DEFAULT_CONSUMER_GROUP == groupname) {
    THROW_MQEXCEPTION(MQClientException,
                      "consumerGroup can not equal " + DEFAULT_CONSUMER_GROUP + ", please specify another one.", -1);
  }

  // messageModel
  if (getDefaultLitePullConsumerConfig()->message_model() != BROADCASTING &&
      getDefaultLitePullConsumerConfig()->message_model() != CLUSTERING) {
    THROW_MQEXCEPTION(MQClientException, "messageModel is valid", -1);
  }

  // allocateMessageQueueStrategy
  if (nullptr == getDefaultLitePullConsumerConfig()->allocate_mq_strategy()) {
    THROW_MQEXCEPTION(MQClientException, "allocateMessageQueueStrategy is null", -1);
  }

  // if (getDefaultLitePullConsumerConfig()->getConsumerTimeoutMillisWhenSuspend() <
  //     getDefaultLitePullConsumerConfig()->getBrokerSuspendMaxTimeMillis()) {
  //   THROW_MQEXCEPTION(
  //       MQClientException,
  //       "Long polling mode, the consumer consumerTimeoutMillisWhenSuspend must greater than
  //       brokerSuspendMaxTimeMillis",
  //       -1);
  // }
}

void DefaultLitePullConsumerImpl::startScheduleTask() {
  scheduled_executor_service_.schedule(
      std::bind(&DefaultLitePullConsumerImpl::fetchTopicMessageQueuesAndComparePeriodically, this), 1000 * 10,
      time_unit::milliseconds);
}

void DefaultLitePullConsumerImpl::fetchTopicMessageQueuesAndComparePeriodically() {
  try {
    fetchTopicMessageQueuesAndCompare();
  } catch (std::exception& e) {
    LOG_ERROR_NEW("ScheduledTask fetchMessageQueuesAndCompare exception: {}", e.what());
  }

  // next round
  scheduled_executor_service_.schedule(
      std::bind(&DefaultLitePullConsumerImpl::fetchTopicMessageQueuesAndComparePeriodically, this),
      getDefaultLitePullConsumerConfig()->topic_metadata_check_interval_millis(), time_unit::milliseconds);
}

void DefaultLitePullConsumerImpl::fetchTopicMessageQueuesAndCompare() {
  std::lock_guard<std::mutex> lock(mutex_);  // synchronized
  for (const auto& it : topic_message_queue_change_listener_map_) {
    const auto& topic = it.first;
    auto* topic_message_queue_change_listener = it.second;
    std::vector<MQMessageQueue> old_message_queues = message_queues_for_topic_[topic];
    std::vector<MQMessageQueue> new_message_queues = fetchMessageQueues(topic);
    bool isChanged = !isSetEqual(new_message_queues, old_message_queues);
    if (isChanged) {
      message_queues_for_topic_[topic] = new_message_queues;
      if (topic_message_queue_change_listener != nullptr) {
        topic_message_queue_change_listener->onChanged(topic, new_message_queues);
      }
    }
  }
}

bool DefaultLitePullConsumerImpl::isSetEqual(std::vector<MQMessageQueue>& new_message_queues,
                                             std::vector<MQMessageQueue>& old_message_queues) {
  if (new_message_queues.size() != old_message_queues.size()) {
    return false;
  }
  std::sort(new_message_queues.begin(), new_message_queues.end());
  std::sort(old_message_queues.begin(), old_message_queues.end());
  return new_message_queues == old_message_queues;
}

void DefaultLitePullConsumerImpl::operateAfterRunning() {
  // If subscribe function invoke before start function, then update topic subscribe info after initialization.
  if (subscription_type_ == SubscriptionType::SUBSCRIBE) {
    updateTopicSubscribeInfoWhenSubscriptionChanged();
  }
  // If assign function invoke before start function, then update pull task after initialization.
  else if (subscription_type_ == SubscriptionType::ASSIGN) {
    auto message_queues = assigned_message_queue_->messageQueues();
    updateAssignPullTask(message_queues);
  }

  for (const auto& it : topic_message_queue_change_listener_map_) {
    const auto& topic = it.first;
    auto messageQueues = fetchMessageQueues(topic);
    message_queues_for_topic_[topic] = std::move(messageQueues);
  }
  // client_instance_->checkClientInBroker();
}

void DefaultLitePullConsumerImpl::updateTopicSubscribeInfoWhenSubscriptionChanged() {
  auto& subTable = rebalance_impl_->getSubscriptionInner();
  for (const auto& it : subTable) {
    const auto& topic = it.first;
    bool ret = client_instance_->updateTopicRouteInfoFromNameServer(topic);
    if (!ret) {
      LOG_WARN_NEW("The topic:[{}] not exist", topic);
    }
  }
}

void DefaultLitePullConsumerImpl::updateAssignPullTask(std::vector<MQMessageQueue>& mq_new_set) {
  std::sort(mq_new_set.begin(), mq_new_set.end());
  std::lock_guard<std::mutex> lock(task_table_mutex_);
  for (auto it = task_table_.begin(); it != task_table_.end();) {
    auto& mq = it->first;
    if (!std::binary_search(mq_new_set.begin(), mq_new_set.end(), mq)) {
      it->second->set_cancelled(true);
      it = task_table_.erase(it);
      continue;
    }
    it++;
  }
  startPullTask(mq_new_set);
}

void DefaultLitePullConsumerImpl::shutdown() {
  switch (service_state_) {
    case CREATE_JUST:
      break;
    case RUNNING:
      persistConsumerOffset();
      client_instance_->unregisterConsumer(client_config_->group_name());
      scheduled_thread_pool_executor_.shutdown();
      scheduled_executor_service_.shutdown();
      client_instance_->shutdown();
      rebalance_impl_->destroy();
      service_state_ = ServiceState::SHUTDOWN_ALREADY;
      LOG_INFO_NEW("the consumer [{}] shutdown OK", client_config_->group_name());
      break;
    default:
      break;
  }
}

void DefaultLitePullConsumerImpl::subscribe(const std::string& topic, const std::string& subExpression) {
  std::lock_guard<std::mutex> lock(mutex_);  // synchronized
  try {
    if (topic.empty()) {
      THROW_MQEXCEPTION(MQClientException, "Topic can not be null or empty.", -1);
    }
    set_subscription_type(SubscriptionType::SUBSCRIBE);
    rebalance_impl_->setSubscriptionData(topic, FilterAPI::buildSubscriptionData(topic, subExpression));

    message_queue_listener_.reset(new MessageQueueListenerImpl(shared_from_this()));
    assigned_message_queue_->set_rebalance_impl(rebalance_impl_.get());

    if (service_state_ == ServiceState::RUNNING) {
      client_instance_->sendHeartbeatToAllBrokerWithLock();
      updateTopicSubscribeInfoWhenSubscriptionChanged();
    }
  } catch (std::exception& e) {
    THROW_MQEXCEPTION2(MQClientException, "subscribe exception", -1, std::make_exception_ptr(e));
  }
}

void DefaultLitePullConsumerImpl::subscribe(const std::string& topic, const MessageSelector& selector) {
  // TODO:
}

void DefaultLitePullConsumerImpl::unsubscribe(const std::string& topic) {
  // TODO:
}

std::vector<SubscriptionData> DefaultLitePullConsumerImpl::subscriptions() const {
  std::vector<SubscriptionData> result;
  auto& subTable = rebalance_impl_->getSubscriptionInner();
  for (const auto& it : subTable) {
    result.push_back(*(it.second));
  }
  return result;
}

void DefaultLitePullConsumerImpl::updateTopicSubscribeInfo(const std::string& topic,
                                                           std::vector<MQMessageQueue>& info) {
  rebalance_impl_->setTopicSubscribeInfo(topic, info);
}

void DefaultLitePullConsumerImpl::doRebalance() {
  if (rebalance_impl_ != nullptr) {
    rebalance_impl_->doRebalance(false);
  }
}

void DefaultLitePullConsumerImpl::updateAssignedMessageQueue(const std::string& topic,
                                                             std::vector<MQMessageQueue>& assigned_message_queue) {
  assigned_message_queue_->updateAssignedMessageQueue(topic, assigned_message_queue);
}

void DefaultLitePullConsumerImpl::updatePullTask(const std::string& topic, std::vector<MQMessageQueue>& mq_new_set) {
  std::sort(mq_new_set.begin(), mq_new_set.end());
  std::lock_guard<std::mutex> lock(task_table_mutex_);
  for (auto it = task_table_.begin(); it != task_table_.end();) {
    auto& mq = it->first;
    if (mq.topic() == topic) {
      // remove unnecessary PullTask
      if (!std::binary_search(mq_new_set.begin(), mq_new_set.end(), mq)) {
        it->second->set_cancelled(true);
        it = task_table_.erase(it);
        continue;
      }
    }
    it++;
  }
  startPullTask(mq_new_set);
}

void DefaultLitePullConsumerImpl::startPullTask(std::vector<MQMessageQueue>& mq_set) {
  for (const auto& mq : mq_set) {
    // add new PullTask
    if (task_table_.find(mq) == task_table_.end()) {
      auto pull_task = std::make_shared<PullTaskImpl>(shared_from_this(), mq);
      task_table_.emplace(mq, pull_task);
      scheduled_thread_pool_executor_.submit(std::bind(&PullTaskImpl::run, pull_task));
    }
  }
}

int64_t DefaultLitePullConsumerImpl::nextPullOffset(const MQMessageQueue& message_queue) {
  int64_t offset = -1;
  int64_t seek_offset = assigned_message_queue_->getSeekOffset(message_queue);
  if (seek_offset != -1) {
    offset = seek_offset;
    assigned_message_queue_->updateConsumeOffset(message_queue, offset);
    assigned_message_queue_->setSeekOffset(message_queue, -1);
  } else {
    offset = assigned_message_queue_->getPullOffset(message_queue);
    if (offset == -1) {
      offset = fetchConsumeOffset(message_queue);
    }
  }
  return offset;
}

int64_t DefaultLitePullConsumerImpl::fetchConsumeOffset(const MQMessageQueue& messageQueue) {
  // checkServiceState();
  return rebalance_impl_->computePullFromWhere(messageQueue);
}

std::unique_ptr<PullResult> DefaultLitePullConsumerImpl::pull(const MQMessageQueue& mq,
                                                              SubscriptionData* subscription_data,
                                                              int64_t offset,
                                                              int max_nums) {
  return pull(mq, subscription_data, offset, max_nums,
              getDefaultLitePullConsumerConfig()->consumer_pull_timeout_millis());
}

std::unique_ptr<PullResult> DefaultLitePullConsumerImpl::pull(const MQMessageQueue& mq,
                                                              SubscriptionData* subscription_data,
                                                              int64_t offset,
                                                              int max_nums,
                                                              long timeout) {
  return pullSyncImpl(mq, subscription_data, offset, max_nums,
                      getDefaultLitePullConsumerConfig()->long_polling_enable(), timeout);
}

std::unique_ptr<PullResult> DefaultLitePullConsumerImpl::pullSyncImpl(const MQMessageQueue& mq,
                                                                      SubscriptionData* subscription_data,
                                                                      int64_t offset,
                                                                      int max_nums,
                                                                      bool block,
                                                                      long timeout) {
  if (offset < 0) {
    THROW_MQEXCEPTION(MQClientException, "offset < 0", -1);
  }

  if (max_nums <= 0) {
    THROW_MQEXCEPTION(MQClientException, "maxNums <= 0", -1);
  }

  int sysFlag = PullSysFlag::buildSysFlag(false, block, true, false, true);

  long timeoutMillis = block ? getDefaultLitePullConsumerConfig()->consumer_timeout_millis_when_suspend() : timeout;

  bool isTagType = ExpressionType::isTagType(subscription_data->expression_type());

  std::unique_ptr<PullResult> pull_result(pull_api_wrapper_->pullKernelImpl(
      mq,                                                                    // mq
      subscription_data->sub_string(),                                       // subExpression
      subscription_data->expression_type(),                                  // expressionType
      isTagType ? 0L : subscription_data->sub_version(),                     // subVersion
      offset,                                                                // offset
      max_nums,                                                              // maxNums
      sysFlag,                                                               // sysFlag
      0,                                                                     // commitOffset
      getDefaultLitePullConsumerConfig()->broker_suspend_max_time_millis(),  // brokerSuspendMaxTimeMillis
      timeoutMillis,                                                         // timeoutMillis
      CommunicationMode::SYNC,                                               // communicationMode
      nullptr));                                                             // pullCallback

  return pull_api_wrapper_->processPullResult(mq, std::move(pull_result), subscription_data);
}

void DefaultLitePullConsumerImpl::submitConsumeRequest(ConsumeRequest* consume_request) {
  consume_request_cache_.push_back(consume_request);
}

void DefaultLitePullConsumerImpl::updatePullOffset(const MQMessageQueue& message_queue, int64_t next_pull_offset) {
  if (assigned_message_queue_->getSeekOffset(message_queue) == -1) {
    assigned_message_queue_->updatePullOffset(message_queue, next_pull_offset);
  }
}

std::vector<MQMessageExt> DefaultLitePullConsumerImpl::poll() {
  return poll(getDefaultLitePullConsumerConfig()->poll_timeout_millis());
}

std::vector<MQMessageExt> DefaultLitePullConsumerImpl::poll(long timeout) {
  // checkServiceState();
  if (auto_commit_) {
    maybeAutoCommit();
  }

  int64_t endTime = UtilAll::currentTimeMillis() + timeout;

  auto consume_request = consume_request_cache_.pop_front(timeout, time_unit::milliseconds);
  if (endTime - UtilAll::currentTimeMillis() > 0) {
    while (consume_request != nullptr && consume_request->process_queue()->dropped()) {
      consume_request = consume_request_cache_.pop_front();
      if (endTime - UtilAll::currentTimeMillis() <= 0) {
        break;
      }
    }
  }

  if (consume_request != nullptr && !consume_request->process_queue()->dropped()) {
    auto& messages = consume_request->message_exts();
    long offset = consume_request->process_queue()->removeMessage(messages);
    assigned_message_queue_->updateConsumeOffset(consume_request->message_queue(), offset);
    // If namespace not null , reset Topic without namespace.
    resetTopic(messages);
    return MQMessageExt::from_list(messages);
  }

  return std::vector<MQMessageExt>();
}

void DefaultLitePullConsumerImpl::maybeAutoCommit() {
  auto now = UtilAll::currentTimeMillis();
  if (now >= next_auto_commit_deadline_) {
    commitAll();
    next_auto_commit_deadline_ = now + getDefaultLitePullConsumerConfig()->auto_commit_interval_millis();
  }
}

void DefaultLitePullConsumerImpl::resetTopic(std::vector<MessageExtPtr>& msg_list) {
  if (msg_list.empty()) {
    return;
  }

  // If namespace not null , reset Topic without namespace.
  const auto& name_space = getDefaultLitePullConsumerConfig()->name_space();
  if (!name_space.empty()) {
    for (auto& message_ext : msg_list) {
      message_ext->set_topic(NamespaceUtil::withoutNamespace(message_ext->topic(), name_space));
    }
  }
}

void DefaultLitePullConsumerImpl::commitAll() {
  try {
    std::vector<MQMessageQueue> message_queues = assigned_message_queue_->messageQueues();
    for (const auto& message_queue : message_queues) {
      long consumer_offset = assigned_message_queue_->getConsumerOffset(message_queue);
      if (consumer_offset != -1) {
        auto process_queue = assigned_message_queue_->getProcessQueue(message_queue);
        if (process_queue != nullptr && !process_queue->dropped()) {
          updateConsumeOffset(message_queue, consumer_offset);
        }
      }
    }
    if (getDefaultLitePullConsumerConfig()->message_model() == MessageModel::BROADCASTING) {
      offset_store_->persistAll(message_queues);
    }
  } catch (std::exception& e) {
    LOG_ERROR_NEW("An error occurred when update consume offset Automatically.");
  }
}

void DefaultLitePullConsumerImpl::updateConsumeOffset(const MQMessageQueue& mq, int64_t offset) {
  // checkServiceState();
  offset_store_->updateOffset(mq, offset, false);
}

void DefaultLitePullConsumerImpl::persistConsumerOffset() {
  if (isServiceStateOk()) {
    std::vector<MQMessageQueue> allocated_mqs;
    if (subscription_type_ == SubscriptionType::SUBSCRIBE) {
      allocated_mqs = rebalance_impl_->getAllocatedMQ();
    } else if (subscription_type_ == SubscriptionType::ASSIGN) {
      allocated_mqs = assigned_message_queue_->messageQueues();
    }
    offset_store_->persistAll(allocated_mqs);
  }
}

std::vector<MQMessageQueue> DefaultLitePullConsumerImpl::fetchMessageQueues(const std::string& topic) {
  std::vector<MQMessageQueue> result;
  if (isServiceStateOk()) {
    client_instance_->getMQAdminImpl()->fetchSubscribeMessageQueues(topic, result);
    parseMessageQueues(result);
  }
  return result;
}

void DefaultLitePullConsumerImpl::parseMessageQueues(std::vector<MQMessageQueue>& queueSet) {
  const auto& name_space = client_config_->name_space();
  if (name_space.empty()) {
    return;
  }
  for (auto& messageQueue : queueSet) {
    auto user_topic = NamespaceUtil::withoutNamespace(messageQueue.topic(), name_space);
    messageQueue.set_topic(user_topic);
  }
}

void DefaultLitePullConsumerImpl::assign(const std::vector<MQMessageQueue>& messageQueues) {
  // TODO:
}

void DefaultLitePullConsumerImpl::seek(const MQMessageQueue& messageQueue, int64_t offset) {
  // TODO:
}

void DefaultLitePullConsumerImpl::seekToBegin(const MQMessageQueue& message_queue) {
  auto begin = minOffset(message_queue);
  seek(message_queue, begin);
}

void DefaultLitePullConsumerImpl::seekToEnd(const MQMessageQueue& message_queue) {
  auto end = maxOffset(message_queue);
  seek(message_queue, end);
}

int64_t DefaultLitePullConsumerImpl::offsetForTimestamp(const MQMessageQueue& message_queue, int64_t timestamp) {
  return searchOffset(message_queue, timestamp);
}

void DefaultLitePullConsumerImpl::pause(const std::vector<MQMessageQueue>& message_queues) {
  assigned_message_queue_->pause(message_queues);
}

void DefaultLitePullConsumerImpl::resume(const std::vector<MQMessageQueue>& message_queues) {
  assigned_message_queue_->resume(message_queues);
}

void DefaultLitePullConsumerImpl::commitSync() {
  commitAll();
}

int64_t DefaultLitePullConsumerImpl::committed(const MQMessageQueue& message_queue) {
  // checkServiceState();
  auto offset = offset_store_->readOffset(message_queue, ReadOffsetType::MEMORY_FIRST_THEN_STORE);
  if (offset == -2) {
    THROW_MQEXCEPTION(MQClientException, "Fetch consume offset from broker exception", -1);
  }
  return offset;
}

void DefaultLitePullConsumerImpl::registerTopicMessageQueueChangeListener(
    const std::string& topic,
    TopicMessageQueueChangeListener* topicMessageQueueChangeListener) {
  std::lock_guard<std::mutex> lock(mutex_);  // synchronized
  if (topic.empty() || nullptr == topicMessageQueueChangeListener) {
    THROW_MQEXCEPTION(MQClientException, "Topic or listener is null", -1);
  }
  if (topic_message_queue_change_listener_map_.find(topic) != topic_message_queue_change_listener_map_.end()) {
    LOG_WARN_NEW("Topic {} had been registered, new listener will overwrite the old one", topic);
  }

  topic_message_queue_change_listener_map_[topic] = topicMessageQueueChangeListener;
  if (service_state_ == ServiceState::RUNNING) {
    auto messageQueues = fetchMessageQueues(topic);
    message_queues_for_topic_[topic] = std::move(messageQueues);
  }
}

std::unique_ptr<ConsumerRunningInfo> DefaultLitePullConsumerImpl::consumerRunningInfo() {
  std::unique_ptr<ConsumerRunningInfo> info(new ConsumerRunningInfo());

  info->setProperty(ConsumerRunningInfo::PROP_CONSUMER_START_TIMESTAMP, UtilAll::to_string(start_time_));

  info->setSubscriptionSet(subscriptions());

  auto processQueueTable = rebalance_impl_->getProcessQueueTable();
  for (const auto& it : processQueueTable) {
    const auto& mq = it.first;
    const auto& pq = it.second;

    ProcessQueueInfo pq_info;
    pq_info.setCommitOffset(offset_store_->readOffset(mq, MEMORY_FIRST_THEN_STORE));
    pq->fillProcessQueueInfo(pq_info);
    info->setMqTable(mq, pq_info);
  }

  return info;
}

bool DefaultLitePullConsumerImpl::isAutoCommit() const {
  return auto_commit_;
}

void DefaultLitePullConsumerImpl::setAutoCommit(bool auto_commit) {
  auto_commit_ = auto_commit;
}

const std::string& DefaultLitePullConsumerImpl::groupName() const {
  return client_config_->group_name();
}

MessageModel DefaultLitePullConsumerImpl::messageModel() const {
  return getDefaultLitePullConsumerConfig()->message_model();
};

ConsumeType DefaultLitePullConsumerImpl::consumeType() const {
  return CONSUME_ACTIVELY;
}

ConsumeFromWhere DefaultLitePullConsumerImpl::consumeFromWhere() const {
  return getDefaultLitePullConsumerConfig()->consume_from_where();
}

void DefaultLitePullConsumerImpl::set_subscription_type(SubscriptionType subscription_type) {
  if (subscription_type_ == SubscriptionType::NONE) {
    subscription_type_ = subscription_type;
  } else if (subscription_type_ != subscription_type) {
    THROW_MQEXCEPTION(MQClientException, "Subscribe and assign are mutually exclusive.", -1);
  }
}

}  // namespace rocketmq
