/*
 * 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 "ace/Timer_Queue.h"
#include "ace/Timer_Heap.h"
#include "ace/Reactor.h"
#include "ace/svc_export.h"
#include "ace/Timer_Heap_T.h"
#include "ace/Timer_Queue_Adapters.h"

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

#include "RegionExpiryHandler.hpp"
#include "RegionInternal.hpp"

using namespace apache::geode::client;

RegionExpiryHandler::RegionExpiryHandler(std::shared_ptr<RegionInternal>& rptr,
                                         ExpirationAction action,
                                         std::chrono::seconds duration)
    : m_regionPtr(rptr),
      m_action(action),
      m_duration(duration),
      /* adongre
       * CID 28941: Uninitialized scalar field (UNINIT_CTOR)
       */
      m_expiryTaskId(0) {}

int RegionExpiryHandler::handle_timeout(const ACE_Time_Value& current_time,
                                        const void*) {
  auto curr_time = std::chrono::system_clock::from_time_t(current_time.sec());
  try {
    auto statistics = m_regionPtr->getStatistics();
    auto lastTimeForExp = statistics->getLastAccessedTime();
    if (m_regionPtr->getAttributes().getRegionTimeToLive() >
        std::chrono::seconds::zero()) {
      lastTimeForExp = statistics->getLastModifiedTime();
    }

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

int RegionExpiryHandler::handle_close(ACE_HANDLE, ACE_Reactor_Mask) {
  //  we now delete the handler in GF_Timer_Heap_ImmediateReset_T
  // delete this;
  return 0;
}

void RegionExpiryHandler::DoTheExpirationAction() {
  switch (m_action) {
    case ExpirationAction::INVALIDATE: {
      LOGDEBUG(
          "RegionExpiryHandler::DoTheExpirationAction INVALIDATE "
          "region [%s]",
          m_regionPtr->getFullPath().c_str());
      m_regionPtr->invalidateRegionNoThrow(nullptr,
                                           CacheEventFlags::EXPIRATION);
      break;
    }
    case ExpirationAction::LOCAL_INVALIDATE: {
      LOGDEBUG(
          "RegionExpiryHandler::DoTheExpirationAction LOCAL_INVALIDATE "
          "region [%s]",
          m_regionPtr->getFullPath().c_str());
      m_regionPtr->invalidateRegionNoThrow(
          nullptr, CacheEventFlags::EXPIRATION | CacheEventFlags::LOCAL);
      break;
    }
    case ExpirationAction::DESTROY: {
      LOGDEBUG(
          "RegionExpiryHandler::DoTheExpirationAction DESTROY "
          "region [%s]",
          m_regionPtr->getFullPath().c_str());
      m_regionPtr->destroyRegionNoThrow(nullptr, true,
                                        CacheEventFlags::EXPIRATION);
      break;
    }
    case ExpirationAction::LOCAL_DESTROY: {
      LOGDEBUG(
          "RegionExpiryHandler::DoTheExpirationAction LOCAL_DESTROY "
          "region [%s]",
          m_regionPtr->getFullPath().c_str());
      m_regionPtr->destroyRegionNoThrow(
          nullptr, true, CacheEventFlags::EXPIRATION | CacheEventFlags::LOCAL);
      break;
    }
    default: {
      LOGERROR(
          "Unknown expiration action "
          "%d for region [%s]",
          m_action, m_regionPtr->getFullPath().c_str());
      break;
    }
  }
}
