package annotations.tools;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;
import com.sun.tools.javac.main.CommandLine;

import plume.FileIOException;
import annotations.Annotation;
import annotations.Annotations;
import annotations.el.ABlock;
import annotations.el.AClass;
import annotations.el.ADeclaration;
import annotations.el.AElement;
import annotations.el.AExpression;
import annotations.el.AField;
import annotations.el.AMethod;
import annotations.el.AScene;
import annotations.el.ATypeElement;
import annotations.el.ATypeElementWithType;
import annotations.el.AnnotationDef;
import annotations.el.DefException;
import annotations.el.ElementVisitor;
import annotations.field.AnnotationFieldType;
import annotations.io.IndexFileParser;
import annotations.io.IndexFileWriter;

/**
 * Utility for merging index files, including multiple versions for the
 *  same class.
 *
 * @author dbro
 */
public class IndexFileMerger {
  public static void main(String[] args) {
    if (args.length < 1) { System.exit(0); }

    final SetMultimap<String, String> annotatedFor = HashMultimap.create();
    String[] inputArgs;

    // TODO: document assumptions
    // collect annotations into scene
    try {
      try {
        inputArgs = CommandLine.parse(args);
      } catch (IOException ex) {
        System.err.println(ex);
        System.err.println("(For non-argfile beginning with \"@\", use \"@@\" for initial \"@\".");
        System.err.println("Alternative for filenames: indicate directory, e.g. as './@file'.");
        System.err.println("Alternative for flags: use '=', as in '-o=@Deprecated'.)");
        System.exit(1);
        return;  // so compiler knows inputArgs defined after try/catch
      }

      File baseFile = new File(inputArgs[0]);
      boolean byDir = baseFile.isDirectory();
      String basePath = baseFile.getCanonicalPath();
      AScene scene = new AScene();

      for (int i = byDir ? 1 : 0; i < inputArgs.length; i++) {
        File inputFile = new File(inputArgs[i]);
        String inputPath = inputFile.getCanonicalPath();
        String filename = inputFile.getName();

        if (byDir) {
          if (!(filename.endsWith(".jaif") || filename.endsWith("jann"))) {
            System.err.println("WARNING: ignoring non-JAIF " + filename);
            continue;
          }
          if (!inputPath.startsWith(basePath)) {
            System.err.println("WARNING: ignoring file outside base directory "
                + filename);
            continue;
          }

          // note which base subdirectory JAIF came from
          String relPath = inputPath.substring(basePath.length()+1);  // +1 '/'
          int ix = relPath.indexOf(File.separator);
          String subdir = ix < 0 ? relPath : relPath.substring(0, ix);
          // trim .jaif or .jann and subdir, convert directory to package id
          String classname = relPath.substring(0, relPath.lastIndexOf('.'))
              .substring(relPath.indexOf('/')+1).replace(File.separator, ".");
          annotatedFor.put(classname, "\"" + subdir + "\"");
        }

        try {
          IndexFileParser.parseFile(inputPath, scene);
        } catch (FileNotFoundException e) {
          System.err.println("IndexFileMerger: can't read "
              + inputPath);
          System.exit(1);
        } catch (FileIOException e) {
          e.printStackTrace();  // TODO
          System.exit(1);
        }
      }

      if (!byDir) {
/*
        // collect defs
        Map<String, String> annoPkgs = new HashMap<String, String>();
        try {
          new DefCollector(scene) {
            @Override
            protected void visitAnnotationDef(AnnotationDef d) {
              String[] a = d.name.split("\\.");
              if (a.length > 2 && a[a.length-2].matches("quals?")) {
                String s = a[a.length-1];
                annoPkgs.put(s, d.name.substring(0));
              }
            }
          }.visit();
        } catch (DefException e) {
          System.err.println("DefCollector failed!");
          e.printStackTrace();
          System.exit(1);
        }
*/

        for (Map.Entry<String, AClass> entry : scene.classes.entrySet()) {
          // final String classname = entry.getKey();

          entry.getValue().accept(new ElementVisitor<Void, Void>() {
            // Map<String, String> annoPkgs = new HashMap<String, String>();

            // Void process(AElement el) {
            //  for (Annotation anno : el.tlAnnotationsHere) {
            //    AnnotationDef def = anno.def();
            //    String[] a = def.name.split("\\.");
            //    if ("AnnotatedFor".equals(a[a.length-1])) {
            //      @SuppressWarnings("unchecked")
            //      List<String> vals =
            //          (List<String>) anno.getFieldValue("value");
            //      for (String val : vals) {
            //        annotatedFor.put(classname, val);
            //      }
            //    } else if (a.length > 2 && a[a.length-2].matches("quals?")) {
            //      annotatedFor.put(classname, a[a.length-3]);
            //    }
            //  }
            //  return null;
            // }

            Void visit(AElement el) {
              if (el != null) { el.accept(this, null); }
              return null;
            }

            <T, E extends AElement> Void visitMap(Map<T, E> map) {
              if (map != null) {
                for (E el : map.values()) { visit(el); }
              }
              return null;
            }

            @Override
            public Void visitAnnotationDef(AnnotationDef d, Void v) {
              // String[] a = d.name.split("\\.");
              // if (a.length > 2 && a[a.length-2].matches("quals?")) {
              //  String s = a[a.length-1];
              //  annoPkgs.put(s, d.name.substring(0));
              // }
              return null;  // process(d);
            }

            @Override
            public Void visitBlock(ABlock el, Void v) {
              visitMap(el.locals);
              return visitExpression(el, v);
            }

            @Override
            public Void visitClass(AClass el, Void v) {
              visitMap(el.bounds);
              visitMap(el.extendsImplements);
              visitMap(el.instanceInits);
              visitMap(el.staticInits);
              visitMap(el.methods);
              visitMap(el.fields);
              visitMap(el.fieldInits);
              return visitDeclaration(el, v);
            }

            @Override
            public Void visitDeclaration(ADeclaration el, Void v) {
              visitMap(el.insertAnnotations);
              visitMap(el.insertTypecasts);
              return visitElement(el, v);
            }

            @Override
            public Void visitExpression(AExpression el, Void v) {
              visitMap(el.calls);
              visitMap(el.funs);
              visitMap(el.instanceofs);
              visitMap(el.news);
              visitMap(el.refs);
              visitMap(el.typecasts);
              return visitElement(el, v);
            }

            @Override
            public Void visitField(AField el, Void v) {
              visit(el.init);
              return visitDeclaration(el, v);
            }

            @Override
            public Void visitMethod(AMethod el, Void v) {
              visit(el.receiver);
              visitMap(el.parameters);
              visitMap(el.bounds);
              visit(el.returnType);
              visit(el.body);
              visitMap(el.throwsException);
              return visitDeclaration(el, v);
            }

            @Override
            public Void visitTypeElement(ATypeElement el, Void v) {
              visitMap(el.innerTypes);
              return visitElement(el, v);
            }

            @Override
            public Void visitTypeElementWithType(ATypeElementWithType el,
                Void v) {
              return visitTypeElement(el, v);
            }

            @Override
            public Void visitElement(AElement el, Void v) {
              visit(el.type);
              return null;  // process(el);
            }
          }, null);
        }
      }

      // add AnnotatedFor to each annotated class
      AnnotationFieldType stringArray =
          AnnotationFieldType.fromClass(new String[0].getClass(),
              Collections.<String, AnnotationDef>emptyMap());
      AnnotationDef afDef =
          Annotations.createValueAnnotationDef("AnnotatedFor",
              Collections.<Annotation>emptySet(), stringArray);
      for (Map.Entry<String, Collection<String>> entry :
          annotatedFor.asMap().entrySet()) {
        String key = entry.getKey();
        Collection<String> values = entry.getValue();
        Annotation afAnno = new Annotation(afDef, Collections
                .<String, Collection<String>>singletonMap("value", values));
        scene.classes.vivify(key).tlAnnotationsHere.add(afAnno);
      }
      scene.prune();
      annotatedFor.clear();  // for gc

      try {
        IndexFileWriter.write(scene, new PrintWriter(System.out, true));
      } catch (SecurityException e) {
        e.printStackTrace();
        System.exit(1);
      } catch (DefException e) {
        e.printStackTrace();
        System.exit(1);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}
