/**
 * 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.metron.solr.schema;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import org.apache.metron.common.utils.JSONUtils;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;

public class SchemaTranslator {

  public static final String TAB = "  ";
  public static final String PREAMBLE="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
          "<!--\n" +
          " Licensed to the Apache Software Foundation (ASF) under one or more\n" +
          " contributor license agreements.  See the NOTICE file distributed with\n" +
          " this work for additional information regarding copyright ownership.\n" +
          " The ASF licenses this file to You under the Apache License, Version 2.0\n" +
          " (the \"License\"); you may not use this file except in compliance with\n" +
          " the License.  You may obtain a copy of the License at\n" +
          "\n" +
          "     http://www.apache.org/licenses/LICENSE-2.0\n" +
          "\n" +
          " Unless required by applicable law or agreed to in writing, software\n" +
          " distributed under the License is distributed on an \"AS IS\" BASIS,\n" +
          " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" +
          " See the License for the specific language governing permissions and\n" +
          " limitations under the License.\n" +
          "-->";
  public static final String VERSION_FIELD =
          "<field name=\"_version_\" type=\"" + SolrFields.LONG.solrType.getName() + "\" indexed=\"false\" stored=\"false\"/>";
  public static final String ROOT_FIELD =
          "<field name=\"_root_\" type=\"" + SolrFields.STRING.solrType.getName() + "\" indexed=\"true\" stored=\"false\" docValues=\"false\" />";
  public static final String DYNAMIC_FIELD_CATCHALL = "<dynamicField name=\"*\" type=\"ignored\" multiValued=\"false\" docValues=\"true\"/>";
  public static final String UNIQUE_KEY = "<uniqueKey>guid</uniqueKey>";
  public static final String PROPERTIES_KEY = "properties";
  public static final String DYNAMIC_TEMPLATES_KEY = "dynamic_templates";
  public static final String SCHEMA_FORMAT="<schema name=\"%s\" version=\"1.6\">";
  public static final String TEMPLATE_KEY = "template";

  public enum SolrFields {
    STRING( new FieldType("string", "solr.StrField").sortMissingLast()
          , ImmutableSet.of("text", "keyword")),
    BOOLEAN( new FieldType("boolean", "solr.BoolField").sortMissingLast()
           , ImmutableSet.of("boolean")),
    INTEGER( new FieldType("pint", "solr.IntPointField").docValues()
           , ImmutableSet.of("integer")),
    FLOAT( new FieldType("pfloat", "solr.FloatPointField").docValues()
           , ImmutableSet.of("float")),
    LONG( new FieldType("plong", "solr.LongPointField").docValues()
           , ImmutableSet.of("long")),
    DOUBLE( new FieldType("pdouble", "solr.DoublePointField").docValues()
           , ImmutableSet.of("double")),
    BINARY( new FieldType("bytes", "solr.BinaryField").docValues()
           , ImmutableSet.of("binary")),
    LOCATION( new FieldType("location", "solr.LatLonPointSpatialField").docValues()
            , ImmutableSet.of("geo_point")),
    IP(new FieldType("ip", "solr.StrField").sortMissingLast()
      , ImmutableSet.of("ip")),
    TIMESTAMP(new FieldType("timestamp", "solr.LongPointField").docValues()
             , ImmutableSet.of("date")),
    IGNORE( new FieldType("ignored", "solr.StrField").multiValued(), new HashSet<>())
    ;
    FieldType solrType;
    Set<String> elasticsearchTypes;

    SolrFields(FieldType solrType, Set<String> elasticsearchTypes) {
      this.solrType = solrType;
      this.elasticsearchTypes = elasticsearchTypes;
    }

    public String getTypeDeclaration() {
      return solrType.toString();
    }

    public static SolrFields byElasticsearchType(String type) {
      for(SolrFields f : values()) {
        if(f.elasticsearchTypes.contains(type)) {
          return f;
        }
      }
      return null;
    }


    public static void printTypes(PrintWriter pw) {
      for(SolrFields f : values()) {
        pw.println(TAB + f.getTypeDeclaration());
      }
    }
  }

  public static String normalizeField(String fieldName) {
    return fieldName.replace(':', '.');
  }

  public static void processProperties(PrintWriter pw, Map<String, Object> properties) {
    for(Map.Entry<String, Object> property : properties.entrySet()) {
      String fieldName = normalizeField(property.getKey());
      System.out.println("Processing property: " + fieldName);
      if(fieldName.equals("guid")) {
        pw.println(TAB + "<field name=\"guid\" type=\"" + SolrFields.STRING.solrType.getName()
                + "\" indexed=\"true\" stored=\"true\" required=\"true\" multiValued=\"false\" />");
      }
      else {
        String type = (String) ((Map<String, Object>) property.getValue()).get("type");
        SolrFields solrField = SolrFields.byElasticsearchType(type);
        if(solrField == null) {
          System.out.println("Skipping " + fieldName + " because I can't find solr type for " + type);
          continue;
        }
        pw.println(TAB + String.format("<field name=\"%s\" type=\"%s\" indexed=\"true\" stored=\"true\" />", fieldName, solrField.solrType.getName()));
      }
    }
  }

  public static void processDynamicMappings(PrintWriter pw, List<Map<String, Object>> properties) {
    for(Map<String, Object> dynamicProperty : properties) {
      for(Map.Entry<String, Object> dynamicFieldDef : dynamicProperty.entrySet()) {
        System.out.println("Processing dynamic property: " + dynamicFieldDef.getKey());
        Map<String, Object> def = (Map<String, Object>) dynamicFieldDef.getValue();
        String match = (String) def.get("match");
        if(match == null) {
          match = (String) def.get("path_match");
        }
        match = normalizeField(match);
        String type = (String)((Map<String, Object>)def.get("mapping")).get("type");
        SolrFields solrField = SolrFields.byElasticsearchType(type);
        if(solrField == null) {
          System.out.println("Skipping " + match + " because I can't find solr type for " + type);
          continue;
        }
        if(solrField == null) {
          throw new IllegalStateException("Unable to find associated solr type for " + type + " with dynamic property " + solrField);
        }
        pw.println(TAB + String.format("<dynamicField name=\"%s\" type=\"%s\" multiValued=\"false\" docValues=\"true\"/>", match, solrField.solrType.getName()));
      }
    }
  }

  public static void translate(PrintWriter pw, Map<String, Object> template) {
    pw.println(PREAMBLE);
    System.out.println("Processing " + template.getOrDefault(TEMPLATE_KEY, "unknown template"));
    Map<String, Object> mappings = (Map<String, Object>) template.getOrDefault("mappings", new HashMap<>());
    if (mappings.size() != 1) {
      System.err.println("Unable to process mappings. We expect exactly 1 mapping, there are " + mappings.size() + " mappings specified");
    }
    String docName = Iterables.getFirst(mappings.keySet(), null);
    pw.println(String.format(SCHEMA_FORMAT, docName));
    pw.println(TAB + VERSION_FIELD);
    pw.println(TAB + ROOT_FIELD);
    for (Map.Entry<String, Object> docTypeToMapping : mappings.entrySet()) {
      System.out.println("Processing " + docTypeToMapping.getKey() + " doc type");
      Map<String, Object> actualMappings = (Map<String, Object>) docTypeToMapping.getValue();
      Map<String, Object> properties = (Map<String, Object>) actualMappings.getOrDefault(PROPERTIES_KEY, new HashMap<>());
      processProperties(pw, properties);
      List<Map<String, Object>> dynamicMappings = (List<Map<String, Object>>) actualMappings.getOrDefault(DYNAMIC_TEMPLATES_KEY, new ArrayList<>());
      processDynamicMappings(pw, dynamicMappings);
      pw.println(TAB + DYNAMIC_FIELD_CATCHALL);
      pw.println(TAB + UNIQUE_KEY);
      SolrFields.printTypes(pw);
    }
    pw.println("</schema>");
    pw.flush();
  }

  public static void main(String... argv) throws IOException {
    String templateFile = argv[0];
    String schemaFile = argv[1];
    Map<String, Object> template = JSONUtils.INSTANCE.load(new File(templateFile), JSONUtils.MAP_SUPPLIER);
    try(PrintWriter pw = new PrintWriter(new File(schemaFile))) {
      translate(pw, template);
    }
  }
}
