/*
 * Copyright 2012-2014 Institut National des Sciences Appliquées de Lyon (INSA-Lyon)
 *
 * Licensed 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 fr.insalyon.citi.golo.doc;

import fr.insalyon.citi.golo.compiler.parser.ASTCompilationUnit;
import gololang.Predefined;

import java.lang.invoke.MethodHandle;
import java.nio.file.Path;
import java.util.TreeMap;
import java.util.Map;

public class CtagsProcessor extends AbstractProcessor {

  private StringBuilder ctags;
  private String file = "file";

  private String ctagsLine(String name, String address, String field) {
    return String.format("%s\t%s\t%s;\"\t%s\n", name, file, address, field);
  }

  private String ctagsModule(ModuleDocumentation module) {
    return ctagsLine(module.moduleName(), "address", "m");
  }

  private String ctagsFunction(ModuleDocumentation.FunctionDocumentation funct) {
    return ctagsLine("+" + funct.name, "address", "f");
  }

  private String ctagsStruct(String name) {
    return ctagsLine("+" + name, "address", "f");
  }

  @Override
  public String render(ASTCompilationUnit compilationUnit) throws Throwable {
    ModuleDocumentation documentation = new ModuleDocumentation(compilationUnit);
    ctags.append(ctagsModule(documentation));
    for (String structName : documentation.structs().keySet()) {
      ctags.append(ctagsStruct(structName));
      // TODO: members
    }
    for (ModuleDocumentation.FunctionDocumentation funct : documentation.functions()) {
      ctags.append(ctagsFunction(funct));
    }
    return "";
  }

  @Override
  public void process(Map<String, ASTCompilationUnit> units, Path targetFolder) throws Throwable {
    ensureFolderExists(targetFolder);
    ctags = new StringBuilder();
    for (String src : units.keySet()) {
      file = src;
      render(units.get(src));
    }
    Predefined.textToFile(ctags.toString(), targetFolder.resolve("ctags"));
  }
}

@@ -944,16 +944,56 @@
 essor %7B%0A
+  // TODO: compute the address of tags !
 %0A  priva
@@ -1316,17 +1316,17 @@
 ress%22, %22
-m
+p
 %22);%0A  %7D%0A
@@ -1428,144 +1428,903 @@
 tags
-Line(%22+%22 + funct.name, %22address%22, %22f%22);%0A  %7D%0A%0A  private String ctagsStruct(String name) %7B%0A    return ctagsLine(%22+%22 + name, %22address%22, %22f%22
+Function(funct, %22%22);%0A  %7D%0A  private String ctagsFunction(ModuleDocumentation.FunctionDocumentation funct, String parent) %7B%0A    // TODO: signature (args)%0A    // TODO: add local functions%0A    // TODO: %22arity%22 field%0A    // TODO: %22file:%22 field for local functions%0A    String fields = %22f%22;%0A    String prefix = %22+%22;%0A    if (parent != %22%22) %7B%0A      fields += %22%5Ctclass:%22 + parent;%0A    %7D%0A    String name = prefix + funct.name;%0A    return ctagsLine(name, %22address%22, fields);%0A  %7D%0A%0A  private String ctagsAugment(String name) %7B%0A    return ctagsLine(name, %22address%22, %22a%22);%0A  %7D%0A%0A  private String ctagsStruct(String name) %7B%0A    return ctagsLine(%22+%22 + name, %22address%22, %22s%22);%0A  %7D%0A%0A  private String ctagsStructMember(String struct, String member) %7B%0A    String visibility = %22+%22;%0A    if (member.charAt(0) == '_') %7B%0A      visibility = %22-%22;%0A    %7D%0A    return ctagsLine(visibility + member, %22address%22, %22m%5Ctstruct:%22 + struct
 );%0A 
@@ -2541,24 +2541,45 @@
 entation));%0A
+    // TODO: imports%0A
     for (Str
@@ -2686,30 +2686,494 @@
     
-// TODO: members%0A    %7D
+for (String member : documentation.structMembers().get(structName)) %7B%0A        ctags.append(ctagsStructMember(structName, member));%0A      %7D%0A    %7D%0A    for (String augmentName : documentation.augmentations().keySet()) %7B%0A      ctags.append(ctagsAugment(augmentName));%0A      for (ModuleDocumentation.FunctionDocumentation funct : documentation.augmentationFunctions().get(augmentName)) %7B%0A        ctags.append(ctagsFunction(funct, augmentName));%0A      %7D%0A    %7D%0A    // TODO: module level states
 %0A   

add several kinds of ctags