package com.chenyang.druid.sql.dialect.es.visitor;

import java.util.ArrayList;
import java.util.List;
import util.StringJoin;

public class MappingTree {
   private String index;
   private String mapping;
   private String name;
   private String dataType;
   private MappingTree parent;
   private Type type;
   private List<MappingTree> children;

   public MappingTree() {
      this.type = Type.field;
      this.children = new ArrayList();
   }

   public Type getType() {
      return this.type;
   }

   public void setType(Type type) {
      this.type = type;
   }

   public MappingTree getParent() {
      return this.parent;
   }

   public void setParent(MappingTree parent) {
      this.parent = parent;
   }

   public List<MappingTree> getChildren() {
      return this.children;
   }

   public void setChildren(List<MappingTree> children) {
      this.children = children;
   }

   public String getName() {
      return this.name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public MappingTree create() {
      MappingTree tree = new MappingTree();
      this.children.add(tree);
      tree.parent = this;
      return tree;
   }

   public String getIndex() {
      return this.index;
   }

   public void setIndex(String index) {
      this.index = index;
   }

   public String getDataType() {
      return this.dataType;
   }

   public void setDataType(String dataType) {
      this.dataType = dataType;
   }

   public String getMapping() {
      return this.mapping;
   }

   public void setMapping(String mapping) {
      this.mapping = mapping;
   }

   public List<MappingTree> getFlatValues() {
      List<String> footprint = new ArrayList();
      List<MappingTree> flatNames = new ArrayList();
      this.visit(this.children, footprint, flatNames);
      return flatNames;
   }

   private void visit(List<MappingTree> children, List<String> footprint, List<MappingTree> flatNames) {
      if (children != null && children.size() != 0) {
         for(MappingTree child : children) {
            if (child.getChildren().size() == 0) {
               String index = null;
               String mapping = null;
               if (child.getType() == Type.field) {
                  index = (String)footprint.remove(0);
                  mapping = (String)footprint.remove(0);
               }

               footprint.add(child.getName());
               String name = StringJoin.join(footprint, ".");
               footprint.remove(footprint.size() - 1);
               if (child.getType() == Type.field) {
                  footprint.add(0, mapping);
                  footprint.add(0, index);
               }

               MappingTree item = new MappingTree();
               item.setIndex(child.getType() == Type.index ? child.getName() : index);
               item.setMapping(child.getType() == Type.mapping ? child.getName() : mapping);
               item.setName(name);
               item.setType(child.getType());
               item.setDataType(child.getDataType());
               flatNames.add(item);
            } else {
               footprint.add(child.getName());
               this.visit(child.getChildren(), footprint, flatNames);
               footprint.remove(footprint.size() - 1);
            }
         }

      }
   }

   public static enum Type {
      index,
      mapping,
      field;
   }
}
