/*
 * 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 "CqEventImpl.hpp"

#include <geode/CacheableString.hpp>

#include "TcrMessage.hpp"
#include "ThinClientCacheDistributionManager.hpp"
#include "ThinClientPoolHADM.hpp"

namespace apache {
namespace geode {
namespace client {
CqEventImpl::CqEventImpl(std::shared_ptr<CqQuery>& cQuery, CqOperation baseOp,
                         CqOperation cqOp, std::shared_ptr<CacheableKey>& key,
                         std::shared_ptr<Cacheable>& value,
                         ThinClientBaseDM* tcrdm,
                         std::shared_ptr<CacheableBytes> deltaBytes,
                         std::shared_ptr<EventId> eventId)
    : m_error(false) {
  m_cQuery = cQuery;
  m_queryOp = cqOp;
  m_baseOp = baseOp;
  m_key = key;
  m_newValue = value;
  if (m_queryOp == CqOperation::OP_TYPE_INVALID) m_error = true;
  m_tcrdm = tcrdm;
  m_deltaValue = deltaBytes;
  m_eventId = eventId;
}
std::shared_ptr<CqQuery> CqEventImpl::getCq() const { return m_cQuery; }

CqOperation CqEventImpl::getBaseOperation() const { return m_baseOp; }

/**
 * Get the the operation on the query results. Supported operations include
 * update, create, and destroy.
 */
CqOperation CqEventImpl::getQueryOperation() const { return m_queryOp; }

/**
 * Get the key relating to the event.
 * @return Object key.
 */
std::shared_ptr<CacheableKey> CqEventImpl::getKey() const { return m_key; }
/**
 * Get the new value of the modification.
 *  If there is no new value because this is a delete, then
 *  return null.
 */
std::shared_ptr<Cacheable> CqEventImpl::getNewValue() const {
  if (m_deltaValue == nullptr) {
    return m_newValue;
  } else {
    // Get full object for delta
    TcrMessageRequestEventValue fullObjectMsg(
        new DataOutput(
            m_tcrdm->getConnectionManager().getCacheImpl()->createDataOutput()),
        m_eventId);
    TcrMessageReply reply(true, nullptr);
    ThinClientPoolHADM* poolHADM = dynamic_cast<ThinClientPoolHADM*>(m_tcrdm);
    GfErrType err = GF_NOTCON;
    if (poolHADM) {
      err = poolHADM->sendRequestToPrimary(fullObjectMsg, reply);
    } else {
      err = static_cast<ThinClientCacheDistributionManager*>(m_tcrdm)
                ->sendRequestToPrimary(fullObjectMsg, reply);
    }
    std::shared_ptr<Cacheable> fullObject = nullptr;
    if (err == GF_NOERR) {
      fullObject = reply.getValue();
    }
    return fullObject;
  }
}

bool CqEventImpl::getError() { return m_error; }

std::string CqEventImpl::toString() {
  char buffer[1024];
  ACE_OS::snprintf(
      buffer, 1024,
      "CqEvent CqName=%s; base operation=%d; cq operation= %d;key=%s;value=%s",
      m_cQuery->getName().c_str(), static_cast<int>(m_baseOp),
      static_cast<int>(m_queryOp), m_key->toString().c_str(),
      m_newValue->toString().c_str());
  return buffer;
}
std::shared_ptr<CacheableBytes> CqEventImpl::getDeltaValue() const {
  return m_deltaValue;
}

}  // namespace client
}  // namespace geode
}  // namespace apache
