/*
 * Copyright 2012-2013 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.*;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;

class ModuleDocumentation {

  private String moduleName;
  private String moduleDocumentation;

  private final Map<String, String> functionsMap = new TreeMap<>();
  private final Map<String, String> augmentationsMap = new TreeMap<>();
  private final Map<String, Map<String, String>> augmentationsFunctionsMap = new TreeMap<>();

  ModuleDocumentation(ASTCompilationUnit compilationUnit) {
    new ModuleVisitor().visit(compilationUnit, null);
  }

  public String getModuleName() {
    return moduleName;
  }

  public String getModuleDocumentation() {
    return moduleDocumentation;
  }

  public Map<String, String> getFunctionsMap() {
    return functionsMap;
  }

  public Map<String, String> getAugmentationsMap() {
    return augmentationsMap;
  }

  public Map<String, Map<String, String>> getAugmentationsFunctionsMap() {
    return augmentationsFunctionsMap;
  }

  private String documentationOrNothing(String documentation) {
    return (documentation != null) ? documentation : "\n";
  }

  private class ModuleVisitor implements GoloParserVisitor {

    private String currentAugmentation = null;

    @Override
    public Object visit(SimpleNode node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTerror node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTCompilationUnit node, Object data) {
      node.childrenAccept(this, data);
      return data;
    }

    @Override
    public Object visit(ASTModuleDeclaration node, Object data) {
      moduleName = node.getName();
      moduleDocumentation = documentationOrNothing(node.getDocumentation());
      return data;
    }

    @Override
    public Object visit(ASTImportDeclaration node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTToplevelDeclaration node, Object data) {
      node.childrenAccept(this, data);
      return data;
    }

    @Override
    public Object visit(ASTAugmentDeclaration node, Object data) {
      currentAugmentation = node.getName();
      augmentationsMap.put(node.getName(), documentationOrNothing(node.getDocumentation()));
      augmentationsFunctionsMap.put(node.getName(), new TreeMap<String, String>());
      node.childrenAccept(this, data);
      currentAugmentation = null;
      return data;
    }

    @Override
    public Object visit(ASTFunctionDeclaration node, Object data) {
      Map<String, String> target = node.isAugmentation() ? augmentationsFunctionsMap.get(currentAugmentation) : functionsMap;
      target.put(node.getName(), documentationOrNothing(node.getDocumentation()));
      return data;
    }

    @Override
    public Object visit(ASTContinue node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTBreak node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTThrow node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTWhileLoop node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTForLoop node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTForEachLoop node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTTryCatchFinally node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTUnaryExpression node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTCommutativeExpression node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTAssociativeExpression node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTMethodInvocation node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTBlock node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTFunction node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTLiteral node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTReference node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTLetOrVar node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTAssignment node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTReturn node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTFunctionInvocation node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTConditionalBranching node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTCase node, Object data) {
      return data;
    }

    @Override
    public Object visit(ASTMatch node, Object data) {
      return data;
    }
  }
}

@@ -750,129 +750,175 @@
 til.
-Collections;%0Aimport java.util.LinkedHashMap;%0Aimport java.util.Map;%0Aimport java.util.TreeMap;%0A%0Aclass ModuleDocumentation %7B
+*;%0A%0Aclass ModuleDocumentation %7B%0A%0A  static class FunctionDocumentation %7B%0A    public String name;%0A    public String documentation;%0A    public List%3CString%3E arguments;%0A  %7D
 %0A%0A  
@@ -1999,16 +1999,87 @@
  = null;
+%0A    private FunctionDocumentation currentFunctionDocumentation = null;
 %0A%0A    @O
@@ -3564,24 +3564,287 @@
 tation()));%0A
+      currentFunctionDocumentation = new FunctionDocumentation();%0A      currentFunctionDocumentation.name = node.getName();%0A      currentFunctionDocumentation.documentation = documentationOrNothing(node.getDocumentation());%0A      node.childrenAccept(this, data);%0A
       return
@@ -5126,32 +5126,239 @@
  Object data) %7B%0A
+      if (currentFunctionDocumentation != null) %7B%0A        currentFunctionDocumentation.arguments = node.getArguments();%0A        // TODO do something here%0A        currentFunctionDocumentation = null;%0A      %7D%0A
       return dat

Work in progress