/*
 * 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 "PullRequest.h"
#include "Logging.h"

namespace rocketmq {
//<!***************************************************************************
const uint64 PullRequest::RebalanceLockInterval = 20 * 1000;
const uint64 PullRequest::RebalanceLockMaxLiveTime = 30 * 1000;
/**
 * If the process queue has not been pulled for more than MAX_PULL_IDLE_TIME, we need to mark it as dropped
 * default 120s
 */
const uint64 PullRequest::MAX_PULL_IDLE_TIME = 120 * 1000;

PullRequest::PullRequest(const string& groupname)
    : m_groupname(groupname), m_nextOffset(0), m_queueOffsetMax(0), m_bDropped(false), m_bLocked(false) {
  m_lastLockTimestamp = UtilAll::currentTimeMillis();
  m_lastPullTimestamp = UtilAll::currentTimeMillis();
  m_lastConsumeTimestamp = UtilAll::currentTimeMillis();
}

PullRequest::~PullRequest() {
  m_msgTreeMapTemp.clear();
  m_msgTreeMap.clear();
}

PullRequest& PullRequest::operator=(const PullRequest& other) {
  boost::lock_guard<boost::mutex> lock(m_pullRequestLock);
  if (this != &other) {
    m_groupname = other.m_groupname;
    m_nextOffset = other.m_nextOffset;
    m_bDropped.store(other.m_bDropped.load());
    m_queueOffsetMax = other.m_queueOffsetMax;
    m_messageQueue = other.m_messageQueue;
    m_msgTreeMap = other.m_msgTreeMap;
    m_msgTreeMapTemp = other.m_msgTreeMapTemp;
    m_lastPullTimestamp = other.m_lastPullTimestamp;
    m_lastConsumeTimestamp = other.m_lastConsumeTimestamp;
  }
  return *this;
}

void PullRequest::putMessage(vector<MQMessageExt>& msgs) {
  boost::lock_guard<boost::mutex> lock(m_pullRequestLock);

  vector<MQMessageExt>::iterator it = msgs.begin();
  for (; it != msgs.end(); it++) {
    m_msgTreeMap[it->getQueueOffset()] = *it;
    m_queueOffsetMax = (std::max)(m_queueOffsetMax, it->getQueueOffset());
  }
  LOG_DEBUG("PullRequest: putMessage m_queueOffsetMax:%lld ", m_queueOffsetMax);
}

void PullRequest::getMessage(vector<MQMessageExt>& msgs) {
  boost::lock_guard<boost::mutex> lock(m_pullRequestLock);

  map<int64, MQMessageExt>::iterator it = m_msgTreeMap.begin();
  for (; it != m_msgTreeMap.end(); it++) {
    msgs.push_back(it->second);
  }
}

int64 PullRequest::getCacheMinOffset() {
  boost::lock_guard<boost::mutex> lock(m_pullRequestLock);
  if (m_msgTreeMap.empty()) {
    return 0;
  } else {
    map<int64, MQMessageExt>::iterator it = m_msgTreeMap.begin();
    MQMessageExt msg = it->second;
    return msg.getQueueOffset();
  }
}

int64 PullRequest::getCacheMaxOffset() {
  return m_queueOffsetMax;
}

int PullRequest::getCacheMsgCount() {
  boost::lock_guard<boost::mutex> lock(m_pullRequestLock);
  return m_msgTreeMap.size() + m_msgTreeMapTemp.size();
}

void PullRequest::getMessageByQueueOffset(vector<MQMessageExt>& msgs, int64 minQueueOffset, int64 maxQueueOffset) {
  boost::lock_guard<boost::mutex> lock(m_pullRequestLock);

  int64 it = minQueueOffset;
  for (; it <= maxQueueOffset; it++) {
    msgs.push_back(m_msgTreeMap[it]);
  }
}

int64 PullRequest::removeMessage(vector<MQMessageExt>& msgs) {
  boost::lock_guard<boost::mutex> lock(m_pullRequestLock);

  int64 result = -1;
  LOG_DEBUG("m_queueOffsetMax is:%lld", m_queueOffsetMax);
  if (!m_msgTreeMap.empty()) {
    result = m_queueOffsetMax + 1;
    LOG_DEBUG(" offset result is:%lld, m_queueOffsetMax is:%lld, msgs size:" SIZET_FMT "", result, m_queueOffsetMax,
              msgs.size());
    vector<MQMessageExt>::iterator it = msgs.begin();
    for (; it != msgs.end(); it++) {
      LOG_DEBUG("remove these msg from m_msgTreeMap, its offset:%lld", it->getQueueOffset());
      m_msgTreeMap.erase(it->getQueueOffset());
    }

    if (!m_msgTreeMap.empty()) {
      map<int64, MQMessageExt>::iterator it = m_msgTreeMap.begin();
      result = it->first;
      LOG_INFO("cache msg size:" SIZET_FMT " of pullRequest:%s, return offset result is:%lld", m_msgTreeMap.size(),
               m_messageQueue.toString().c_str(), result);
    }
  }

  return result;
}

void PullRequest::clearAllMsgs() {
  boost::lock_guard<boost::mutex> lock(m_pullRequestLock);

  if (isDropped()) {
    LOG_DEBUG("clear m_msgTreeMap as PullRequest had been dropped.");
    m_msgTreeMap.clear();
    m_msgTreeMapTemp.clear();
  }
}

void PullRequest::updateQueueMaxOffset(int64 queueOffset) {
  // following 2 cases which may set queueOffset smaller than m_queueOffsetMax:
  // 1. resetOffset cmd
  // 2. during  rebalance, if configured with CONSUMER_FROM_FIRST_OFFSET, when
  // readOffset called by computePullFromWhere was failed,  m_nextOffset will be
  // setted to 0
  m_queueOffsetMax = queueOffset;
}

void PullRequest::setDropped(bool dropped) {
  int temp = (dropped == true ? 1 : 0);
  m_bDropped.store(temp);
  /*
  m_queueOffsetMax = 0;
  m_nextOffset = 0;
  //the reason why not clear m_queueOffsetMax and m_nextOffset is due to
  ConsumeMsgService and drop mq are concurrent running.
      consider following situation:
      1>. ConsumeMsgService running
      2>. dorebalance, drop mq, reset m_nextOffset and m_queueOffsetMax
      3>. ConsumeMsgService calls removeMessages, if no other msgs in
  m_msgTreeMap, m_queueOffsetMax(0)+1 will return;
      4>. updateOffset with 1, which is more smaller than correct offset.
  */
}

bool PullRequest::isDropped() const {
  return m_bDropped.load() == 1;
}

int64 PullRequest::getNextOffset() {
  boost::lock_guard<boost::mutex> lock(m_pullRequestLock);
  return m_nextOffset;
}

void PullRequest::setLocked(bool Locked) {
  int temp = (Locked == true ? 1 : 0);
  m_bLocked.store(temp);
}

bool PullRequest::isLocked() const {
  return m_bLocked.load() == 1;
}

bool PullRequest::isLockExpired() const {
  return (UtilAll::currentTimeMillis() - m_lastLockTimestamp) > RebalanceLockMaxLiveTime;
}

void PullRequest::setLastLockTimestamp(int64 time) {
  m_lastLockTimestamp = time;
}

int64 PullRequest::getLastLockTimestamp() const {
  return m_lastLockTimestamp;
}

void PullRequest::setLastPullTimestamp(uint64 time) {
  m_lastPullTimestamp = time;
}

uint64 PullRequest::getLastPullTimestamp() const {
  return m_lastPullTimestamp;
}

bool PullRequest::isPullRequestExpired() const {
  uint64 interval = m_lastPullTimestamp + MAX_PULL_IDLE_TIME;
  if (interval <= UtilAll::currentTimeMillis()) {
    LOG_WARN("PullRequest for [%s] has been expired %lld ms,m_lastPullTimestamp = %lld ms",
             m_messageQueue.toString().c_str(), UtilAll::currentTimeMillis() - m_lastPullTimestamp,
             m_lastPullTimestamp);
    return true;
  }
  return false;
}

void PullRequest::setLastConsumeTimestamp(uint64 time) {
  m_lastConsumeTimestamp = time;
}

uint64 PullRequest::getLastConsumeTimestamp() const {
  return m_lastConsumeTimestamp;
}

void PullRequest::setTryUnlockTimes(int time) {
  m_lastLockTimestamp = time;
}

int PullRequest::getTryUnlockTimes() const {
  return m_lastLockTimestamp;
}

void PullRequest::setNextOffset(int64 nextoffset) {
  boost::lock_guard<boost::mutex> lock(m_pullRequestLock);
  m_nextOffset = nextoffset;
}

string PullRequest::getGroupName() const {
  return m_groupname;
}

boost::timed_mutex& PullRequest::getPullRequestCriticalSection() {
  return m_consumeLock;
}

void PullRequest::takeMessages(vector<MQMessageExt>& msgs, int batchSize) {
  boost::lock_guard<boost::mutex> lock(m_pullRequestLock);
  for (int i = 0; i != batchSize; i++) {
    map<int64, MQMessageExt>::iterator it = m_msgTreeMap.begin();
    if (it != m_msgTreeMap.end()) {
      msgs.push_back(it->second);
      m_msgTreeMapTemp[it->first] = it->second;
      m_msgTreeMap.erase(it);
    }
  }
}

void PullRequest::makeMessageToCosumeAgain(vector<MQMessageExt>& msgs) {
  boost::lock_guard<boost::mutex> lock(m_pullRequestLock);
  for (unsigned int it = 0; it != msgs.size(); ++it) {
    m_msgTreeMap[msgs[it].getQueueOffset()] = msgs[it];
    m_msgTreeMapTemp.erase(msgs[it].getQueueOffset());
  }
}

int64 PullRequest::commit() {
  boost::lock_guard<boost::mutex> lock(m_pullRequestLock);
  if (!m_msgTreeMapTemp.empty()) {
    int64 offset = (--m_msgTreeMapTemp.end())->first;
    m_msgTreeMapTemp.clear();
    return offset + 1;
  } else {
    return -1;
  }
}

//<!***************************************************************************
}  // namespace rocketmq
