package com.cloudera.cmf.service.impala;

import com.cloudera.cmf.model.DbRole;
import com.cloudera.cmf.model.DbService;
import com.cloudera.cmf.model.Enums.ConfigScope;
import com.cloudera.cmf.persist.CmfEntityManager;
import com.cloudera.cmf.service.DependencyUtils;
import com.cloudera.cmf.service.ServiceHandler;
import com.cloudera.cmf.service.ServiceHandlerRegistry;
import com.cloudera.cmf.service.Validation;
import com.cloudera.cmf.service.ValidationContext;
import com.cloudera.cmf.service.config.AbstractParamSpecValidator;
import com.cloudera.cmf.service.config.BooleanParamSpec;
import com.cloudera.cmf.service.config.NumericParamSpec;
import com.cloudera.cmf.service.config.ParamParseException;
import com.cloudera.cmf.service.config.ParamSpec;
import com.cloudera.cmf.service.yarn.YarnParams;
import com.cloudera.cmf.service.yarn.YarnServiceHandler.RoleNames;
import com.cloudera.cmf.version.Release;
import com.cloudera.enterprise.MessageWithArgs;
import com.google.common.collect.Lists;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;

public class ImpalaYarnRMValidator extends AbstractParamSpecValidator<DbService>
{
  private static final String MESSAGE_KEY_PREFIX = "message.impala.yarnrmvalidator.validation";
  public static final String MESSAGE_KEY_FAILURE_DYNAMIC_RESOURCE_POOLS_REQUIRED = "message.impala.yarnrmvalidator.validationFailureDynamicResourcePoolsRequired";
  public static final String MESSAGE_KEY_FAILURE_CGROUPS_REQUIRED = "message.impala.yarnrmvalidator.validationFailureCgroupsRequired";
  public static final String MESSAGE_KEY_FAILURE_LCE_REQUIRED = "message.impala.yarnrmvalidator.validationFailureLCERequired";
  public static final String MESSAGE_KEY_FAILURE_MIN_MEMORY_NOT_ZERO = "message.impala.yarnrmvalidator.validationFailureMinMemoryNotZero";
  public static final String MESSAGE_KEY_FAILURE_MIN_VCORES_NOT_ZERO = "message.impala.yarnrmvalidator.validationFailureMinVCoresNotZero";
  public static final String MESSAGE_KEY_SUCCESS_YARN_CONFIGURED_CORRECTLY = "message.impala.yarnrmvalidator.validationSuccessYarnConfiguredCorrectly";

  public ImpalaYarnRMValidator()
  {
    super(ImpalaParams.YARN_FOR_RM, false, "impala_yarn_resource_management_validator");
  }

  protected Collection<Validation> performValidation(ServiceHandlerRegistry shr, ValidationContext context, Release serviceVersion, Map<String, String> configsMap, DbService yarnDependency)
    throws ParamParseException
  {
    if (Enums.ConfigScope.SERVICE != context.getLevel()) {
      return Collections.emptyList();
    }

    if (yarnDependency == null) {
      return Collections.emptyList();
    }

    DbService impala = context.getService();

    DbService yarn = DependencyUtils.getDependencyService(impala, shr.get(impala), shr, ImpalaParams.YARN_FOR_RM, CmfEntityManager.currentCmfEntityManager());

    Release sVer = yarn.getServiceVersion();
    boolean cgroups = ((Boolean)YarnParams.YARN_ENABLE_CGROUPS.extractFromStringMap(yarn.getServiceConfigsMap(), sVer)).booleanValue();

    boolean useLce = ((Boolean)YarnParams.YARN_ENABLE_LINUX_CONTAINER_EXECUTOR_ALWAYS.extractFromStringMap(yarn.getServiceConfigsMap(), sVer)).booleanValue();

    boolean kerberos = shr.get(yarn).requiresCredentials(CmfEntityManager.currentCmfEntityManager(), yarn);

    Collection validations = Lists.newArrayList();
    if (!cgroups) {
      validations.add(Validation.error(context, MessageWithArgs.of("message.impala.yarnrmvalidator.validationFailureCgroupsRequired", new String[] { YarnParams.YARN_ENABLE_CGROUPS.getDisplayName() })));
    }

    if ((!kerberos) && (!useLce)) {
      validations.add(Validation.error(context, MessageWithArgs.of("message.impala.yarnrmvalidator.validationFailureLCERequired", new String[] { YarnParams.YARN_ENABLE_LINUX_CONTAINER_EXECUTOR_ALWAYS.getDisplayName() })));
    }

    for (DbRole rm : yarn.getRolesWithType(YarnServiceHandler.RoleNames.RESOURCEMANAGER.name())) {
      Map configs = rm.getConfigsMap();
      if (((Long)YarnParams.RM_SCHEDULER_MEMORY_MIN.extractFromStringMap(configs, sVer)).longValue() != 0L) {
        validations.add(Validation.error(context, MessageWithArgs.of("message.impala.yarnrmvalidator.validationFailureMinMemoryNotZero", new String[] { YarnParams.RM_SCHEDULER_MEMORY_MIN.getDisplayName() })));
      }

      if (((Long)YarnParams.RM_SCHEDULER_VCORES_MIN.extractFromStringMap(configs, sVer)).longValue() != 0L) {
        validations.add(Validation.error(context, MessageWithArgs.of("message.impala.yarnrmvalidator.validationFailureMinVCoresNotZero", new String[] { YarnParams.RM_SCHEDULER_VCORES_MIN.getDisplayName() })));
      }

    }

    boolean dynamicResourcePoolsEnabled = ((Boolean)ImpalaParams.DYNAMIC_RESOURCE_POOLS_ENABLED.extractFromStringMap(impala.getServiceConfigsMap(), impala.getServiceVersion())).booleanValue();

    if (!dynamicResourcePoolsEnabled) {
      validations.add(Validation.error(context, MessageWithArgs.of("message.impala.yarnrmvalidator.validationFailureDynamicResourcePoolsRequired", new String[] { ImpalaParams.DYNAMIC_RESOURCE_POOLS_ENABLED.getDisplayName() })));
    }

    if (validations.isEmpty()) {
      validations.add(Validation.check(context, MessageWithArgs.of("message.impala.yarnrmvalidator.validationSuccessYarnConfiguredCorrectly", new String[0])));
    }

    return validations;
  }
}