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

#include "CacheImpl.hpp"
#include "ExpiryTaskManager.hpp"
#include "RegionInternal.hpp"

namespace apache {
namespace geode {
namespace client {

EntryExpiryHandler::EntryExpiryHandler(std::shared_ptr<RegionInternal>& rptr,
                                       std::shared_ptr<MapEntryImpl>& entryPtr,
                                       ExpirationAction action,
                                       std::chrono::seconds duration)
    : m_regionPtr(rptr),
      m_entryPtr(entryPtr),
      m_action(action),
      m_duration(duration) {}

int EntryExpiryHandler::handle_timeout(const ACE_Time_Value& current_time,
                                       const void*) {
  std::shared_ptr<CacheableKey> key;
  m_entryPtr->getKeyI(key);
  ExpEntryProperties& expProps = m_entryPtr->getExpProperties();
  try {
    auto curr_time = std::chrono::system_clock::from_time_t(current_time.sec());

    auto lastTimeForExp = expProps.getLastAccessTime();
    if (m_regionPtr->getAttributes().getEntryTimeToLive() >
        std::chrono::seconds::zero()) {
      lastTimeForExp = expProps.getLastModifiedTime();
    }

    auto elapsed = curr_time - lastTimeForExp;

    LOGDEBUG("Entered entry expiry task handler for key [%s] of region [%s]",
             Utils::nullSafeToString(key).c_str(),
             m_regionPtr->getFullPath().c_str());
    if (elapsed >= m_duration) {
      DoTheExpirationAction(key);
    } else {
      // reset the task after
      // (lastAccessTime + entryExpiryDuration - curr_time) in seconds
      auto remaining = m_duration - elapsed;
      LOGDEBUG("Resetting expiry task for key [%s] of region [%s]",
               Utils::nullSafeToString(key).c_str(),
               m_regionPtr->getFullPath().c_str());
      m_regionPtr->getCacheImpl()->getExpiryTaskManager().resetTask(
          expProps.getExpiryTaskId(), remaining);
      return 0;
    }
  } catch (...) {
    // Ignore whatever exception comes
  }
  LOGDEBUG("Removing expiry task for key [%s] of region [%s]",
           Utils::nullSafeToString(key).c_str(),
           m_regionPtr->getFullPath().c_str());
  m_regionPtr->getCacheImpl()->getExpiryTaskManager().resetTask(
      expProps.getExpiryTaskId(), std::chrono::seconds::zero());
  //  we now delete the handler in GF_Timer_Heap_ImmediateReset_T
  // and always return success.

  // set the invalid taskid as we have removed the expiry task
  expProps.setExpiryTaskId(-1);
  return 0;
}

int EntryExpiryHandler::handle_close(ACE_HANDLE, ACE_Reactor_Mask) {
  delete this;
  return 0;
}

inline void EntryExpiryHandler::DoTheExpirationAction(
    const std::shared_ptr<CacheableKey>& key) {
  // Pass a blank version tag.
  std::shared_ptr<VersionTag> versionTag;
  switch (m_action) {
    case ExpirationAction::INVALIDATE: {
      LOGDEBUG(
          "EntryExpiryHandler::DoTheExpirationAction INVALIDATE "
          "for region %s entry with key %s",
          m_regionPtr->getFullPath().c_str(),
          Utils::nullSafeToString(key).c_str());
      m_regionPtr->invalidateNoThrow(key, nullptr, -1,
                                     CacheEventFlags::EXPIRATION, versionTag);
      break;
    }
    case ExpirationAction::LOCAL_INVALIDATE: {
      LOGDEBUG(
          "EntryExpiryHandler::DoTheExpirationAction LOCAL_INVALIDATE "
          "for region %s entry with key %s",
          m_regionPtr->getFullPath().c_str(),
          Utils::nullSafeToString(key).c_str());
      m_regionPtr->invalidateNoThrow(
          key, nullptr, -1,
          CacheEventFlags::EXPIRATION | CacheEventFlags::LOCAL, versionTag);
      break;
    }
    case ExpirationAction::DESTROY: {
      LOGDEBUG(
          "EntryExpiryHandler::DoTheExpirationAction DESTROY "
          "for region %s entry with key %s",
          m_regionPtr->getFullPath().c_str(),
          Utils::nullSafeToString(key).c_str());
      m_regionPtr->destroyNoThrow(key, nullptr, -1, CacheEventFlags::EXPIRATION,
                                  versionTag);
      break;
    }
    case ExpirationAction::LOCAL_DESTROY: {
      LOGDEBUG(
          "EntryExpiryHandler::DoTheExpirationAction LOCAL_DESTROY "
          "for region %s entry with key %s",
          m_regionPtr->getFullPath().c_str(),
          Utils::nullSafeToString(key).c_str());
      m_regionPtr->destroyNoThrow(
          key, nullptr, -1,
          CacheEventFlags::EXPIRATION | CacheEventFlags::LOCAL, versionTag);
      break;
    }
    case ExpirationAction::INVALID_ACTION: {
      LOGERROR(
          "Unknown expiration action "
          "%d for region %s for key %s",
          m_action, m_regionPtr->getFullPath().c_str(),
          Utils::nullSafeToString(key).c_str());
      break;
    }
  }
}

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