/**
 * IBM Confidential
 * 
 * OCO Source Materials
 * 
 * IBM Cognos Products: predict-sa-suggestion
 * 
 * (C) Copyright IBM Corp. 2020
 * 
 * The source code for this program is not published or otherwise
 * divested of its trade secrets, irrespective of what has been
 * deposited with the U.S. Copyright Office.
 */
package com.ibm.bi.predict.sa.suggestion.rules;

import static com.ibm.bi.predict.sa.suggestion.rules.domain.RuleFieldType.ANY;
import static com.ibm.bi.predict.sa.suggestion.rules.domain.RuleFieldType.CATEGORICAL;
import static com.ibm.bi.predict.sa.suggestion.rules.domain.RuleFieldType.CATEGORICAL_NONDATETIME;
import static com.ibm.bi.predict.sa.suggestion.rules.domain.RuleFieldType.CONTINUOUS;
import static com.ibm.bi.predict.sa.suggestion.rules.domain.RuleFieldType.DATETIME;
import static com.ibm.bi.predict.sa.suggestion.rules.domain.RuleFieldType.NOT_ALLOWED;
import static com.ibm.bi.predict.sa.suggestion.rules.domain.RuleInsightType.AVERAGE;
import static com.ibm.bi.predict.sa.suggestion.rules.domain.RuleInsightType.MODE;
import static com.ibm.bi.predict.sa.suggestion.rules.domain.RuleInsightType.MEANINGFUL_DIFFERENCES;
import static com.ibm.bi.predict.sa.suggestion.rules.domain.RuleInsightType.PREDICTIVE_STRENGTH;
import static com.ibm.bi.predict.sa.suggestion.rules.domain.RuleInsightType.FIT_LINE;
import static com.ibm.bi.predict.sa.suggestion.rules.domain.RuleInsightType.TIME_SERIES;
import static com.ibm.bi.predict.sa.suggestion.rules.domain.RuleRequiredStatistics.ROW_COUNT;
import static com.ibm.bi.predict.sa.suggestion.rules.domain.RuleRequiredStatistics.SUM_SQR;
import static com.ibm.bi.predict.types.RoleType.EXPLANATORY;
import static com.ibm.bi.predict.types.RoleType.GROUP;
import static com.ibm.bi.predict.types.RoleType.OTHER;
import static com.ibm.bi.predict.types.RoleType.REFERENCE;
import static com.ibm.bi.predict.types.RoleType.REPEAT;
import static com.ibm.bi.predict.types.RoleType.RESPONSE;
import static com.ibm.bi.predict.types.RoleType.WEIGHT;
import static java.util.Arrays.asList;

import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;

import com.ibm.bi.predict.sa.suggestion.domain.parameters.AnnotationParameter;
import com.ibm.bi.predict.sa.suggestion.domain.parameters.AnnotationRestrictionEnumeration;
import com.ibm.bi.predict.sa.suggestion.domain.parameters.AnnotationRestrictionNumber;
import com.ibm.bi.predict.sa.suggestion.rules.domain.RuleAlgorithm;
import com.ibm.bi.predict.sa.suggestion.rules.domain.RuleInsight;
import com.ibm.bi.predict.sa.suggestion.rules.domain.RuleInsightType;
import com.ibm.bi.predict.sa.suggestion.rules.domain.RulePattern;
import com.ibm.bi.predict.sa.suggestion.rules.domain.RulePatternRole;
import com.ibm.bi.predict.sa.suggestion.rules.domain.RuleSummarization;
import com.ibm.bi.predict.types.Identifiable;

/**
 * MACHINE GENERATED FILE FOR SMART ANNOTATION RULES
 */

public final class Rules {

  private Rules() {
    // Prevent instantiation
  }


  ##{{GENERATED}}##


  public static RulePattern pattern(String id) {
    return PATTERNS.get(id);
  }


  public static RuleInsight insight(String id) {
    return INSIGHTS.stream().collect(Collectors.toMap(
      Identifiable::id,
      Function.identity(),
      (oldVal, newVal) -> oldVal,
      LinkedHashMap::new
    )).get(id);
  }


  public static RuleAlgorithm algorithm(String id) {
    return ALGORITHMS.get(id);
  }


  private static Map<RuleInsightType, List<String>> algorithms(String ...algos) {
     return Arrays.stream(algos)
      .filter(StringUtils::isNotBlank)
      .map(Rules::algorithmsToList)
      .flatMap(Collection::stream)
      .collect(Collectors.groupingBy(
        algoId -> algorithm(algoId).insightType(),
        LinkedHashMap::new,
        Collectors.mapping(
          Function.identity(),
          Collectors.toList()
        )
      ));
  }


  private static List<String> algorithmsToList(String allAlgos) {
    return Arrays.asList(allAlgos.split(","));
  }


  private static Optional<Number> getOptionalNumber(String v) {
    try {
      return Optional.of(Double.parseDouble(v));
    } catch (Exception e) {
      return Optional.empty();
    }
  }


  private static List<AnnotationParameter> modelParameters(String ... list) {
    return Arrays.stream(list)
        .map(String::trim)
        .filter(s -> !s.isEmpty())      // allows modelParameters("") for convenience of code generation
        .map(PARAMETERS::get)
      .collect(Collectors.toList());
  }
}
