/*
 * 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.
 */
package org.apache.geode.management.internal.cli.functions;

import static org.apache.geode.management.internal.cli.functions.CliFunctionResult.StatusState.ERROR;
import static org.apache.geode.management.internal.cli.functions.CliFunctionResult.StatusState.OK;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.logging.log4j.Logger;
import org.apache.shiro.subject.Subject;

import org.apache.geode.cache.Cache;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.execute.Execution;
import org.apache.geode.cache.execute.Function;
import org.apache.geode.cache.execute.FunctionContext;
import org.apache.geode.cache.execute.FunctionService;
import org.apache.geode.cache.execute.ResultCollector;
import org.apache.geode.cache.query.RegionNotFoundException;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.internal.ClassPathLoader;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.cache.execute.InternalFunction;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.security.SecurityService;
import org.apache.geode.management.internal.cli.i18n.CliStrings;
import org.apache.geode.security.AuthenticationRequiredException;
import org.apache.geode.security.ResourcePermission;

/**
 * @since GemFire 7.0
 */
public class UserFunctionExecution implements InternalFunction<Object[]> {
  private static final long serialVersionUID = 1L;
  private static final Logger logger = LogService.getLogger();
  public static final String ID = UserFunctionExecution.class.getName();

  @Override
  public boolean isHA() {
    return false;
  }

  @Override
  public String getId() {
    return UserFunctionExecution.ID;
  }

  @Override
  public Collection<ResourcePermission> getRequiredPermissions(String regionName) {
    return Collections.emptySet();
  }

  boolean loginRequired(SecurityService securityService) {
    try {
      // if the function is executed on a server with jmx-manager that user is already logged into
      // then we do not need to do login/logout here.
      Subject subject = securityService.getSubject();
      return subject == null || !subject.isAuthenticated();
    } catch (AuthenticationRequiredException e) {
      return true;
    }
  }

  Function<?> loadFunction(String functionId) {
    return FunctionService.getFunction(functionId);
  }

  String[] parseArguments(String argumentsString) {
    if (argumentsString != null && argumentsString.length() > 0) {
      return argumentsString.split(",");
    } else {
      return null;
    }
  }

  Set<String> parseFilters(String filterString) {
    if (filterString != null && filterString.length() > 0) {
      return Arrays.stream(filterString.split(",")).collect(Collectors.toSet());
    } else {
      return new HashSet<>();
    }
  }

  ResultCollector parseResultCollector(String resultCollectorName)
      throws ClassNotFoundException, IllegalAccessException, InstantiationException {
    if (resultCollectorName != null && resultCollectorName.length() > 0) {
      return (ResultCollector) ClassPathLoader.getLatest().forName(resultCollectorName)
          .newInstance();
    } else {
      return null;
    }
  }

  Execution buildExecution(Cache cache, String onRegion) throws RegionNotFoundException {
    Execution execution;
    DistributedMember member = cache.getDistributedSystem().getDistributedMember();

    if (onRegion != null && onRegion.length() > 0) {
      Region region = cache.getRegion(onRegion);

      if (region == null) {
        throw new RegionNotFoundException(onRegion);
      }

      execution = FunctionService.onRegion(region);
    } else {
      execution = FunctionService.onMember(member);
    }

    return execution;
  }

  @Override
  public void execute(FunctionContext<Object[]> context) {
    Cache cache = ((InternalCache) context.getCache()).getCacheForProcessingClientRequests();
    DistributedMember member = cache.getDistributedSystem().getDistributedMember();

    Object[] args = context.getArguments();
    if (args == null) {
      context.getResultSender().lastResult(new CliFunctionResult(context.getMemberName(), ERROR,
          CliStrings.EXECUTE_FUNCTION__MSG__COULD_NOT_RETRIEVE_ARGUMENTS));
      return;
    }

    String functionId = ((String) args[0]);
    String filterString = ((String) args[1]);
    String resultCollectorName = ((String) args[2]);
    String argumentsString = ((String) args[3]);
    String onRegion = ((String) args[4]);
    Properties credentials = (Properties) args[5];
    SecurityService securityService = ((InternalCache) context.getCache()).getSecurityService();

    boolean loginSuccessful = false;
    try {

      // Authenticate If Needed
      if (loginRequired(securityService)) {
        securityService.login(credentials);
        loginSuccessful = true;
      }

      // Load User Function
      Function<?> function = loadFunction(functionId);
      if (function == null) {
        context.getResultSender()
            .lastResult(new CliFunctionResult(context.getMemberName(), ERROR,
                (CliStrings.format(
                    CliStrings.EXECUTE_FUNCTION__MSG__DOES_NOT_HAVE_FUNCTION_0_REGISTERED,
                    functionId))));
        return;
      }

      // Parse Arguments
      Set<String> filters = parseFilters(filterString);
      String[] functionArgs = parseArguments(argumentsString);
      ResultCollector resultCollectorInstance = parseResultCollector(resultCollectorName);

      // Security check
      function.getRequiredPermissions(onRegion, functionArgs).forEach(securityService::authorize);

      // Build & Configure Execution Context
      Execution execution = buildExecution(cache, onRegion);
      if (execution == null) {
        context.getResultSender()
            .lastResult(new CliFunctionResult(context.getMemberName(), ERROR,
                CliStrings.format(
                    CliStrings.EXECUTE_FUNCTION__MSG__ERROR_IN_EXECUTING_0_ON_MEMBER_1_ON_REGION_2_DETAILS_3,
                    functionId, member.getId(), onRegion,
                    CliStrings.EXECUTE_FUNCTION__MSG__ERROR_IN_RETRIEVING_EXECUTOR)));
        return;
      }

      if (resultCollectorInstance != null) {
        execution = execution.withCollector(resultCollectorInstance);
      }

      if (functionArgs != null && functionArgs.length > 0) {
        execution = execution.setArguments(functionArgs);
      }

      if (filters.size() > 0) {
        execution = execution.withFilter(filters);
      }

      // Execute Function and gather results
      List results = null;
      boolean functionSuccess = true;
      List<String> resultMessage = new ArrayList<>();

      ResultCollector rc = execution.execute(function.getId());
      if (function.hasResult()) {
        results = (List) rc.getResult();
      }

      if (results != null) {
        for (Object resultObj : results) {
          if (resultObj != null) {
            if (resultObj instanceof Exception) {
              resultMessage.add(((Exception) resultObj).getMessage());
              functionSuccess = false;
            } else {
              resultMessage.add(resultObj.toString());
            }
          }
        }
      }

      context.getResultSender().lastResult(new CliFunctionResult(context.getMemberName(),
          functionSuccess ? OK : ERROR, resultMessage.toString()));
    } catch (RegionNotFoundException regionNotFoundException) {
      context.getResultSender().lastResult(
          new CliFunctionResult(context.getMemberName(), ERROR, onRegion + " does not exist"));
    } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
      context.getResultSender()
          .lastResult(new CliFunctionResult(context.getMemberName(), ERROR,
              CliStrings.format(
                  CliStrings.EXECUTE_FUNCTION__MSG__RESULT_COLLECTOR_0_NOT_FOUND_ERROR_1,
                  resultCollectorName, e.getMessage())));
    } catch (Exception e) {
      logger.error("error executing function " + functionId, e);
      context.getResultSender().lastResult(
          new CliFunctionResult(context.getMemberName(), ERROR, "Exception: " + e.getMessage()));
    } finally {
      if (loginSuccessful) {
        securityService.logout();
      }
    }
  }
}
