/*
 * 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.commands;

import static org.apache.geode.distributed.ConfigurationProperties.STATISTIC_SAMPLING_ENABLED;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.springframework.shell.core.annotation.CliCommand;
import org.springframework.shell.core.annotation.CliOption;

import org.apache.geode.cache.execute.ResultCollector;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.distributed.internal.InternalConfigurationPersistenceService;
import org.apache.geode.internal.cache.xmlcache.CacheXml;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.logging.log4j.LogLevel;
import org.apache.geode.management.cli.CliMetaData;
import org.apache.geode.management.cli.ConverterHint;
import org.apache.geode.management.cli.GfshCommand;
import org.apache.geode.management.internal.cli.AbstractCliAroundInterceptor;
import org.apache.geode.management.internal.cli.CliUtil;
import org.apache.geode.management.internal.cli.GfshParseResult;
import org.apache.geode.management.internal.cli.functions.AlterRuntimeConfigFunction;
import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
import org.apache.geode.management.internal.cli.i18n.CliStrings;
import org.apache.geode.management.internal.cli.remote.CommandExecutor;
import org.apache.geode.management.internal.cli.result.model.InfoResultModel;
import org.apache.geode.management.internal.cli.result.model.ResultModel;
import org.apache.geode.management.internal.configuration.domain.XmlEntity;
import org.apache.geode.management.internal.security.ResourceOperation;
import org.apache.geode.security.ResourcePermission;

public class AlterRuntimeConfigCommand extends GfshCommand {
  private final AlterRuntimeConfigFunction alterRunTimeConfigFunction =
      new AlterRuntimeConfigFunction();
  private static final Logger logger = LogService.getLogger();

  @CliCommand(value = {CliStrings.ALTER_RUNTIME_CONFIG},
      help = CliStrings.ALTER_RUNTIME_CONFIG__HELP)
  @CliMetaData(relatedTopic = {CliStrings.TOPIC_GEODE_CONFIG},
      interceptor = "org.apache.geode.management.internal.cli.commands.AlterRuntimeConfigCommand$AlterRuntimeInterceptor")
  @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
      operation = ResourcePermission.Operation.MANAGE)
  public ResultModel alterRuntimeConfig(
      @CliOption(key = {CliStrings.MEMBER, CliStrings.MEMBERS},
          optionContext = ConverterHint.ALL_MEMBER_IDNAME,
          help = CliStrings.ALTER_RUNTIME_CONFIG__MEMBER__HELP) String[] memberNameOrId,
      @CliOption(key = {CliStrings.GROUP, CliStrings.GROUPS},
          optionContext = ConverterHint.MEMBERGROUP,
          help = CliStrings.ALTER_RUNTIME_CONFIG__MEMBER__HELP) String[] group,
      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__DISK__SPACE__LIMIT},
          help = CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__DISK__SPACE__LIMIT__HELP) Integer archiveDiskSpaceLimit,
      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__FILE__SIZE__LIMIT},
          help = CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__FILE__SIZE__LIMIT__HELP) Integer archiveFileSizeLimit,
      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__LOG__DISK__SPACE__LIMIT},
          help = CliStrings.ALTER_RUNTIME_CONFIG__LOG__DISK__SPACE__LIMIT__HELP) Integer logDiskSpaceLimit,
      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__LOG__FILE__SIZE__LIMIT},
          help = CliStrings.ALTER_RUNTIME_CONFIG__LOG__FILE__SIZE__LIMIT__HELP) Integer logFileSizeLimit,
      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__LOG__LEVEL},
          optionContext = ConverterHint.LOG_LEVEL,
          help = CliStrings.ALTER_RUNTIME_CONFIG__LOG__LEVEL__HELP) String logLevel,
      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__ARCHIVE__FILE},
          help = CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__ARCHIVE__FILE__HELP) String statisticArchiveFile,
      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__SAMPLE__RATE},
          help = CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__SAMPLE__RATE__HELP) Integer statisticSampleRate,
      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__SAMPLING__ENABLED},
          help = CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__SAMPLING__ENABLED__HELP) Boolean statisticSamplingEnabled,
      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__COPY__ON__READ},
          specifiedDefaultValue = "false",
          help = CliStrings.ALTER_RUNTIME_CONFIG__COPY__ON__READ__HELP) Boolean setCopyOnRead,
      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__LOCK__LEASE},
          help = CliStrings.ALTER_RUNTIME_CONFIG__LOCK__LEASE__HELP) Integer lockLease,
      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__LOCK__TIMEOUT},
          help = CliStrings.ALTER_RUNTIME_CONFIG__LOCK__TIMEOUT__HELP) Integer lockTimeout,
      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__MESSAGE__SYNC__INTERVAL},
          help = CliStrings.ALTER_RUNTIME_CONFIG__MESSAGE__SYNC__INTERVAL__HELP) Integer messageSyncInterval,
      @CliOption(key = {CliStrings.ALTER_RUNTIME_CONFIG__SEARCH__TIMEOUT},
          help = CliStrings.ALTER_RUNTIME_CONFIG__SEARCH__TIMEOUT__HELP) Integer searchTimeout) {

    Map<String, String> runTimeDistributionConfigAttributes = new HashMap<>();
    Map<String, String> rumTimeCacheAttributes = new HashMap<>();
    Set<DistributedMember> targetMembers = findMembers(group, memberNameOrId);

    if (targetMembers.isEmpty()) {
      return ResultModel.createError(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
    }

    if (archiveDiskSpaceLimit != null) {
      runTimeDistributionConfigAttributes.put(
          CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__DISK__SPACE__LIMIT,
          archiveDiskSpaceLimit.toString());
    }

    if (archiveFileSizeLimit != null) {
      runTimeDistributionConfigAttributes.put(
          CliStrings.ALTER_RUNTIME_CONFIG__ARCHIVE__FILE__SIZE__LIMIT,
          archiveFileSizeLimit.toString());
    }

    if (logDiskSpaceLimit != null) {
      runTimeDistributionConfigAttributes.put(
          CliStrings.ALTER_RUNTIME_CONFIG__LOG__DISK__SPACE__LIMIT, logDiskSpaceLimit.toString());
    }

    if (logFileSizeLimit != null) {
      runTimeDistributionConfigAttributes.put(
          CliStrings.ALTER_RUNTIME_CONFIG__LOG__FILE__SIZE__LIMIT, logFileSizeLimit.toString());
    }

    if (logLevel != null && !logLevel.isEmpty()) {
      runTimeDistributionConfigAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__LOG__LEVEL,
          logLevel);
    }

    if (statisticArchiveFile != null && !statisticArchiveFile.isEmpty()) {
      runTimeDistributionConfigAttributes
          .put(CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__ARCHIVE__FILE, statisticArchiveFile);
    }

    if (statisticSampleRate != null) {
      runTimeDistributionConfigAttributes.put(
          CliStrings.ALTER_RUNTIME_CONFIG__STATISTIC__SAMPLE__RATE, statisticSampleRate.toString());
    }

    if (statisticSamplingEnabled != null) {
      runTimeDistributionConfigAttributes.put(STATISTIC_SAMPLING_ENABLED,
          statisticSamplingEnabled.toString());
    }


    // Attributes that are set on the cache.
    if (setCopyOnRead != null) {
      rumTimeCacheAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__COPY__ON__READ,
          setCopyOnRead.toString());
    }

    if (lockLease != null && lockLease > 0 && lockLease < Integer.MAX_VALUE) {
      rumTimeCacheAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__LOCK__LEASE,
          lockLease.toString());
    }

    if (lockTimeout != null && lockTimeout > 0 && lockTimeout < Integer.MAX_VALUE) {
      rumTimeCacheAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__LOCK__TIMEOUT,
          lockTimeout.toString());
    }

    if (messageSyncInterval != null && messageSyncInterval > 0
        && messageSyncInterval < Integer.MAX_VALUE) {
      rumTimeCacheAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__MESSAGE__SYNC__INTERVAL,
          messageSyncInterval.toString());
    }

    if (searchTimeout != null && searchTimeout > 0 && searchTimeout < Integer.MAX_VALUE) {
      rumTimeCacheAttributes.put(CliStrings.ALTER_RUNTIME_CONFIG__SEARCH__TIMEOUT,
          searchTimeout.toString());
    }

    if (runTimeDistributionConfigAttributes.isEmpty() && rumTimeCacheAttributes.isEmpty()) {
      return ResultModel.createError(CliStrings.ALTER_RUNTIME_CONFIG__RELEVANT__OPTION__MESSAGE);
    }

    Map<String, String> allRunTimeAttributes = new HashMap<>();
    allRunTimeAttributes.putAll(runTimeDistributionConfigAttributes);
    allRunTimeAttributes.putAll(rumTimeCacheAttributes);

    ResultCollector<?, ?> rc =
        CliUtil.executeFunction(alterRunTimeConfigFunction, allRunTimeAttributes, targetMembers);
    List<CliFunctionResult> results = CliFunctionResult.cleanResults((List<?>) rc.getResult());
    Set<String> successfulMembers = new TreeSet<>();
    Set<String> errorMessages = new TreeSet<>();

    for (CliFunctionResult result : results) {
      if (result.getThrowable() != null) {
        logger.info("Function failed: " + result.getThrowable());
        errorMessages.add(result.getThrowable().getMessage());
      } else {
        successfulMembers.add(result.getMemberIdOrName());
      }
    }
    final String lineSeparator = System.getProperty("line.separator");


    if (!successfulMembers.isEmpty()) {
      StringBuilder successMessageBuilder = new StringBuilder();

      successMessageBuilder.append(CliStrings.ALTER_RUNTIME_CONFIG__SUCCESS__MESSAGE);
      successMessageBuilder.append(lineSeparator);

      for (String member : successfulMembers) {
        successMessageBuilder.append(member);
        successMessageBuilder.append(lineSeparator);
      }

      Properties properties = new Properties();
      properties.putAll(runTimeDistributionConfigAttributes);

      ResultModel result = new ResultModel();
      InfoResultModel successInfo = result.addInfo("success");
      successInfo.addLine(successMessageBuilder.toString());
      // Set the Cache attributes to be modified
      final XmlEntity xmlEntity = XmlEntity.builder().withType(CacheXml.CACHE)
          .withAttributes(rumTimeCacheAttributes).build();
      InternalConfigurationPersistenceService cps = getConfigurationPersistenceService();
      if (cps == null) {
        successInfo.addLine(CommandExecutor.SERVICE_NOT_RUNNING_CHANGE_NOT_PERSISTED);
      } else {
        cps.modifyXmlAndProperties(properties, xmlEntity, group);
      }
      return result;
    } else {
      StringBuilder errorMessageBuilder = new StringBuilder();
      errorMessageBuilder.append("Following errors occurred while altering runtime config");
      errorMessageBuilder.append(lineSeparator);

      for (String errorMessage : errorMessages) {
        errorMessageBuilder.append(errorMessage);
        errorMessageBuilder.append(lineSeparator);
      }
      return ResultModel.createError(errorMessageBuilder.toString());
    }
  }

  public static class AlterRuntimeInterceptor extends AbstractCliAroundInterceptor {
    @Override
    public ResultModel preExecution(GfshParseResult parseResult) {
      // validate log level
      String logLevel = parseResult.getParamValueAsString("log-level");
      if (StringUtils.isNotBlank(logLevel) && (LogLevel.getLevel(logLevel) == null)) {
        return ResultModel.createError("Invalid log level: " + logLevel);
      }
      return ResultModel.createInfo("");
    }
  }
}
