package joshua.decoder;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.util.List;

import joshua.decoder.ff.FeatureFunction;
import joshua.decoder.ff.lm.KenLMFF;
import joshua.decoder.hypergraph.HyperGraph;
import joshua.decoder.hypergraph.KBestExtractor;
import joshua.decoder.segment_file.Sentence;

/**
 * This class represents translated input objects (sentences or lattices). It is aware of the source
 * sentence and id and contains the decoded hypergraph. Translation objects are returned by
 * DecoderThread instances to the InputHandler, where they are assembled in order for output.
 * 
 * @author Matt Post <post@cs.jhu.edu>
 */

public class Translation {
  private Sentence source;

  /**
   * This stores the output of the translation so we don't have to hold onto the hypergraph while we
   * wait for the outputs to be assembled.
   */
  private String output = null;

  public Translation(Sentence source, HyperGraph hypergraph, KBestExtractor kBestExtractor,
      List<FeatureFunction> featureFunctions, JoshuaConfiguration joshuaConfiguration) {
    this.source = source;

    StringWriter sw = new StringWriter();
    BufferedWriter out = new BufferedWriter(sw);

    try {
      if (hypergraph != null) {
        if (!joshuaConfiguration.hypergraphFilePattern.equals("")) {
          hypergraph.dump(String.format(joshuaConfiguration.hypergraphFilePattern, source.id()), featureFunctions);
        }

        long startTime = System.currentTimeMillis();

        // We must put this weight as zero, otherwise we get an error when we try to retrieve it
        // without checking
        Decoder.weights.put("BLEU", 0);
        kBestExtractor.lazyKBestExtractOnHG(hypergraph, joshuaConfiguration.topN, out);

        if (joshuaConfiguration.rescoreForest) {
          Decoder.weights.put("BLEU", joshuaConfiguration.rescoreForestWeight);
          kBestExtractor.lazyKBestExtractOnHG(hypergraph, joshuaConfiguration.topN, out);

          Decoder.weights.put("BLEU", -joshuaConfiguration.rescoreForestWeight);
          kBestExtractor.lazyKBestExtractOnHG(hypergraph, joshuaConfiguration.topN, out);
        }

        float seconds = (float) (System.currentTimeMillis() - startTime) / 1000.0f;
        Decoder.LOG(1, String.format("[%d] %d-best extraction took %.3f seconds", id(),
            joshuaConfiguration.topN, seconds));

      } else {

        // There is no output for the given input (e.g. blank line)
        // @formatter:off
        String outputString = joshuaConfiguration.outputFormat
            .replace("%s", source.source())
            .replace("%e", "")
            .replace("%S", "")
            .replace("%t", "")
            .replace("%i", Integer.toString(source.id()))
            .replace("%f", "")
            .replace("%c", "0.000");
        // @formatter:on

        out.write(outputString);
        out.newLine();
      }

      out.flush();
    } catch (IOException e) {
      e.printStackTrace();
      System.exit(1);
    }

    /*
     * KenLM hack. If using KenLMFF, we need to tell KenLM to delete the pool used to create chart
     * objects for this sentence.
     */
    for (FeatureFunction feature : featureFunctions) {
      if (feature instanceof KenLMFF) {
        ((KenLMFF) feature).destroyPool(getSourceSentence().id());
        break;
      }
    }

    this.output = sw.toString();
  }

  public Sentence getSourceSentence() {
    return this.source;
  }

  public int id() {
    return source.id();
  }

  @Override
  public String toString() {
    return output;
  }
}

@@ -303,16 +303,67 @@
 ractor;%0A
+import joshua.decoder.hypergraph.ViterbiExtractor;%0A
 import j
@@ -1740,16 +1740,345 @@
 U%22, 0);%0A
+%0A        if (joshuaConfiguration.topN == 0) %7B%0A          String translation = ViterbiExtractor.extractViterbiString(hypergraph.goalNode).trim();%0A          translation = translation.substring(translation.indexOf(' ') + 1, translation.lastIndexOf(' '));%0A          out.write(translation);%0A          out.newLine();%0A        %7D else %7B%0A  
         
@@ -2158,32 +2158,34 @@
  out);%0A%0A        
+ 
+ 
 if (joshuaConfig
@@ -2205,24 +2205,26 @@
 reForest) %7B%0A
+  
           De
@@ -2293,32 +2293,34 @@
 ght);%0A          
+  
 kBestExtractor.l
@@ -2386,32 +2386,34 @@
 ut);%0A%0A          
+ 
+ 
 Decoder.weights.
@@ -2459,32 +2459,34 @@
 eForestWeight);%0A
+  
           kBestE
@@ -2555,24 +2555,36 @@
 topN, out);%0A
+          %7D%0A
         %7D%0A%0A 

Set -top-n 0 to avoid k-best extraction and just get the translation (faster)