package uk.co.bristlecone.voltdb.wrapgen.builder.impl;

import java.util.function.Function;
import java.util.stream.Collectors;

import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeName;

import uk.co.bristlecone.voltdb.wrapgen.builder.ProcData;

/**
 * Provides methods that provide services to a RunnerBuilder, allowing it to create the full class definition.
 * 
 * @author christo
 */
public class RunnerBuilderServices {
  private Function<String, String> packageNamer;
  private Function<String, String> runnerNamer;
  private ProcData procData;

  public RunnerBuilderServices(ProcData procData, Function<String, String> packageNamer,
      Function<String, String> runnerNamer) {
    this.packageNamer = packageNamer;
    this.runnerNamer = runnerNamer;
    this.procData = procData;
  }

  public String procName() {
    return procData.name();
  }

  public String runnerName() {
    return runnerNamer.apply(procName());
  }

  public String procPackageName() {
    return procData.packageName();
  }

  public String runnerPackageName() {
    return packageNamer.apply(procPackageName());
  }

  public String runnerJavaDoc() {
    StringBuilder result = new StringBuilder();
    result.append("An instance of this class can be used to run the <code>");
    result.append(procName());
    result.append("</code> VoltDB stored procedure. This stored procedure's JavaDoc is:\n\n");
    result.append("<blockquote>");
    result.append(procData.classJavaDoc());
    result.append("</blockquote>\n\n");
    result.append("<strong>This class is automatically generated. Manual edits will be overwritten.</strong>\n\n");
    result.append("@author voltdb-wrapgen\n");
    return result.toString();
  }

  /**
   * @return the parameters to the stored procedure's run method, converting them from RunParameter's to ParameterSpec's
   */
  public Iterable<ParameterSpec> runMethodParamsAsParameterSpecs() {
    return procData.parameters()
        .stream()
        .map(rp -> ParameterSpec.builder(TypeName.BYTE, "foo"))
        // .map(rp -> ParameterSpec.builder(ClassName.get(rp.packageName(), rp.typeName()), rp.variableName()))
        .map(psb -> psb.build())
        .collect(Collectors.toList());
  }

  /**
   * @return the parameters to the stored procedure's run method as a comma-separated list of variable names
   */
  public String runMethodParamsAsVariableList() {
    return procData.parameters()
        .stream()
        .map(rp -> rp.variableName())
        .collect(Collectors.joining(", "));
  }
}

@@ -49,16 +49,39 @@
 .impl;%0A%0A
+import java.util.List;%0A
 import j
@@ -145,16 +145,56 @@
 ctors;%0A%0A
+import com.squareup.javapoet.ClassName;%0A
 import c
@@ -232,47 +232,8 @@
 pec;
-%0Aimport com.squareup.javapoet.TypeName;
 %0A%0Aim
@@ -287,16 +287,213 @@
 rocData;
+%0Aimport uk.co.bristlecone.voltdb.wrapgen.source.RunParameter;%0Aimport uk.co.bristlecone.voltdb.wrapgen.source.RunParameterClass;%0Aimport uk.co.bristlecone.voltdb.wrapgen.source.RunParameterPrimitive;
 %0A%0A/**%0A *
@@ -603,17 +603,16 @@
 tion.%0A *
- 
 %0A * @aut
@@ -666,32 +666,38 @@
 ces %7B%0A  private 
+final 
 Function%3CString,
@@ -729,16 +729,22 @@
 private 
+final 
 Function
@@ -783,16 +783,22 @@
 private 
+final 
 ProcData
@@ -840,16 +840,22 @@
 ervices(
+final 
 ProcData
@@ -864,16 +864,22 @@
 rocData,
+ final
  Functio
@@ -916,16 +916,22 @@
 ,%0A      
+final 
 Function
@@ -1418,16 +1418,22 @@
 ) %7B%0A    
+final 
 StringBu
@@ -1992,39 +1992,39 @@
   %7D%0A%0A  /**%0A   * 
-@r
+R
 eturn
+s
  the parameters 
@@ -2099,16 +2099,21 @@
 ter's to
+%0A   *
  Paramet
@@ -2124,32 +2124,260 @@
 ec's
-%0A   */%0A  public Iterable
+. Uses %7B@link RunnerBuilderServices#runParameterToParameterSpecBuilder%7D which internally uses%0A   * %7B@link RunParameter#isPrimitive%7D to dististinguish between reference/class and primitive RunParameter's. Ugly%0A   * manual dispatch :/%0A   */%0A  public List
 %3CPar
@@ -2492,81 +2492,45 @@
 map(
-rp -%3E ParameterSpec.builder(TypeName.BYTE, %22foo%22))%0A        // .map(rp -%3E 
+RunnerBuilderServices::runParameterTo
 Para
@@ -2542,83 +2542,15 @@
 Spec
-.b
+B
 uilder
-(ClassName.get(rp.packageName(), rp.typeName()), rp.variableName())
 )%0A  
@@ -2931,11 +2931,469 @@
 %22));%0A  %7D
+%0A%0A  private static ParameterSpec.Builder runParameterToParameterSpecBuilder(final RunParameter rp) %7B%0A    if(rp.isPrimitive()) %7B%0A      final RunParameterPrimitive rpp = (RunParameterPrimitive) rp;%0A      return ParameterSpec.builder(rpp.typeClass(), rpp.variableName());%0A    %7D else %7B%0A      final RunParameterClass rpc = (RunParameterClass) rp;%0A      return ParameterSpec.builder(ClassName.get(rpc.packageName(), rpc.typeName()), rpc.variableName());%0A    %7D%0A%0A  %7D
 %0A%7D%0A

Fix RunnerBuilderServices#runMethodParamsAsParameterSpecs, add final keywords