/*
 * 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 <geode/AuthenticatedView.hpp>
#include <geode/ExceptionTypes.hpp>
#include <geode/FunctionService.hpp>
#include <geode/PoolManager.hpp>

#include "CacheImpl.hpp"
#include "CacheRegionHelper.hpp"
#include "ExecutionImpl.hpp"
#include "ProxyRegion.hpp"
#include "UserAttributes.hpp"

namespace apache {
namespace geode {
namespace client {

Execution FunctionService::onRegion(const std::shared_ptr<Region>& region) {
  LOGDEBUG("FunctionService::onRegion(std::shared_ptr<Region> region)");
  if (region == nullptr) {
    throw NullPointerException("FunctionService::onRegion: region is null");
  }

  auto realRegion = region;
  const auto& pool = realRegion->getPool();

  if (pool == nullptr) {
    throw IllegalArgumentException("Pool attached with region is closed.");
  }
  AuthenticatedView* authenticatedView = nullptr;

  if (pool->getMultiuserAuthentication()) {
    if (auto pr = std::dynamic_pointer_cast<ProxyRegion>(realRegion)) {
      LOGDEBUG(
          "FunctionService::onRegion(std::shared_ptr<Region> region) proxy "
          "cache");
      // it is in multiuser mode
      authenticatedView = pr->m_authenticatedView;
      auto userAttachedPool = authenticatedView->m_userAttributes->getPool();
      auto pool = realRegion->getCache().getPoolManager().find(
          userAttachedPool->getName());
      if (!(pool != nullptr && pool.get() == userAttachedPool.get() &&
            !pool->isDestroyed())) {
        throw IllegalStateException(
            "Pool has been closed with attached Logical Cache.");
      }
      // getting real region to execute function on region
      if (!realRegion->getCache().isClosed()) {
        realRegion = realRegion->getCache().m_cacheImpl->getRegion(
            realRegion->getName());
      } else {
        throw IllegalStateException("Cache has been closed");
      }

      if (realRegion == nullptr) {
        throw IllegalStateException("Real region has been closed.");
      }
    } else {
      throw IllegalArgumentException(
          "onRegion() argument region should have get from RegionService.");
    }
  }

  return Execution(std::unique_ptr<ExecutionImpl>(
      new ExecutionImpl(realRegion, authenticatedView, pool)));
}

Execution FunctionService::onServerWithPool(const std::shared_ptr<Pool>& pool) {
  if (pool == nullptr) {
    throw NullPointerException("FunctionService::onServer: pool is null");
  }
  if (pool->getMultiuserAuthentication()) {
    throw UnsupportedOperationException(
        "This API is not supported in multiuser mode. "
        "Please use FunctionService::onServer(RegionService) API.");
  }
  return Execution(std::unique_ptr<ExecutionImpl>(new ExecutionImpl(pool)));
}

Execution FunctionService::onServersWithPool(
    const std::shared_ptr<Pool>& pool) {
  if (pool == nullptr) {
    throw NullPointerException("FunctionService::onServers: pool is null");
  }
  if (pool->getMultiuserAuthentication()) {
    throw UnsupportedOperationException(
        "This API is not supported in multiuser mode. "
        "Please use FunctionService::onServers(RegionService) API.");
  }

  return Execution(
      std::unique_ptr<ExecutionImpl>(new ExecutionImpl(pool, true)));
}

Execution FunctionService::onServerWithCache(RegionService& cache) {
  if (cache.isClosed()) {
    throw IllegalStateException("Cache has been closed");
  }

  LOGDEBUG("FunctionService::onServer:");
  if (auto pc = dynamic_cast<AuthenticatedView*>(&cache)) {
    auto userAttachedPool = pc->m_userAttributes->getPool();
    auto pool =
        pc->m_cacheImpl->getPoolManager().find(userAttachedPool->getName());
    if (pool != nullptr && pool.get() == userAttachedPool.get() &&
        !pool->isDestroyed()) {
      return Execution(
          std::unique_ptr<ExecutionImpl>(new ExecutionImpl(pool, false, pc)));
    }
    throw IllegalStateException(
        "Pool has been close to execute function on server");
  } else {
    auto& realcache = static_cast<Cache&>(cache);
    return FunctionService::onServer(
        realcache.m_cacheImpl->getPoolManager().getDefaultPool());
  }
}

Execution FunctionService::onServersWithCache(RegionService& cache) {
  if (cache.isClosed()) {
    throw IllegalStateException("Cache has been closed");
  }

  LOGDEBUG("FunctionService::onServers:");
  if (auto pc = dynamic_cast<AuthenticatedView*>(&cache)) {
    auto userAttachedPool = pc->m_userAttributes->getPool();
    auto pool = pc->m_cacheImpl->getCache()->getPoolManager().find(
        userAttachedPool->getName());
    if (pool != nullptr && pool.get() == userAttachedPool.get() &&
        !pool->isDestroyed()) {
      return Execution(
          std::unique_ptr<ExecutionImpl>(new ExecutionImpl(pool, false, pc)));
    }
    throw IllegalStateException(
        "Pool has been close to execute function on server");
  } else {
    auto& realcache = static_cast<Cache&>(cache);
    return FunctionService::onServers(
        realcache.m_cacheImpl->getPoolManager().getDefaultPool());
  }
}

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