/*
 * 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.
 */
#pragma once

#include <chrono>

#include "MQMessage.h"

ROCKETMQ_NAMESPACE_BEGIN

class MessageAccessor;

class MQMessageExt : public MQMessage {
public:
  MQMessageExt();

  MQMessageExt(const MQMessageExt& other);

  MQMessageExt& operator=(const MQMessageExt& other);

  int32_t getQueueId() const;

  /**
   * @return Milli-seconds since epoch in perspective of system_clock.
   */
  int64_t getBornTimestamp() const;

  std::chrono::system_clock::time_point bornTimestamp() const;

  std::chrono::system_clock::time_point storeTimestamp() const;
  int64_t getStoreTimestamp() const;

  std::string getStoreHost() const;

  int64_t getQueueOffset() const;

  int32_t getDeliveryAttempt() const;

  const std::string& receiptHandle() const;

  bool operator==(const MQMessageExt& other);

  friend class MessageAccessor;
};

ROCKETMQ_NAMESPACE_END