/*
 * GrammarToTextWriter.java
 *
 * Created on 6 maart 2006, 10:30
 *
 */

package DOPParser;

/**
 *
 * @author gideon
 */

import java.io.*;
import java.util.*;

public class Printer {
    
	protected static BufferedWriter out_complete;
	protected static BufferedWriter out_parses;
    
    /** Creates a new instance of GrammarToTextWriter */
    public Printer(Grammar myGrammar) throws IOException {
        
	
    }
    
    public Printer() throws IOException {
    	out_complete = new BufferedWriter(new FileWriter(Main.OUTPUT_DIR + "/" + "output_complete.txt"));
        out_parses = new BufferedWriter(new FileWriter(Main.OUTPUT_DIR + "/" + "parses.txt"));        
        
    }
    
    public static void printToFileTerminalsNonTerminalsAndRules(Grammar myGrammar) throws IOException {
        
        String[] myTerminals = myGrammar.GetListofTerminals();
        
        String[] myNonTerminals = myGrammar.GetListofNonTerminals();
        
        try
        {
           BufferedWriter out = new BufferedWriter(new FileWriter("Output/grammar.txt"));
           
               out.write("TERMINALS");
               out.newLine();
               for (String myTerminal : myTerminals) {
                out.write(myTerminal);
                out.newLine();
               }
               out.write("NONTERMINALS");
               out.newLine();
               for (String myNonTerminal : myNonTerminals) {
                out.write(myNonTerminal);
                out.newLine();
               }

                out.write("PRODUCTION RULES");
                out.newLine();
           
            printRules(myGrammar, out);
       
        out.flush();
        out.close();
         }
        catch (IOException e)    {  System.out.println("ging mis");  }
    }
    
    public static void printRules(Grammar myGrammar, BufferedWriter out) throws IOException {
        
        
        for(NonTerminal nt : myGrammar.nonTerminals.values()){
            //allRules.addAll();
            
            out.write("RULESOFNONTERMINAL " + nt.getName());
                
            out.newLine();
            
            for(Rule myRule : nt.getRules()) {
                StringBuffer rhsStringBuffer = new StringBuffer();
                //make a string out of RHS of rule
                for ( Constituent myConstituent : myRule.getRightHandSide()) {
                    if (myConstituent==null) System.out.println("NullpointerException in Rule: "+ myRule.getLeftHandSide().getName() + "; RHSsize="+ myRule.getRightHandSide().size());
                    else rhsStringBuffer.append(myConstituent.getName());
                    rhsStringBuffer.append('*');
                }
               
                out.write(rhsStringBuffer.toString() + "#" + myRule.getRuleProbability());
                out.newLine();
                
            }
        }	//for(NonTerminal nt : nonTerminals.values())
    }
    
    public static void printRulesToFile(Grammar myGrammar) throws IOException {
        
        try
        {
           BufferedWriter out = new BufferedWriter(new FileWriter("Output/grammar_rules.txt"));
           
        
        for(NonTerminal nt : myGrammar.nonTerminals.values()){
            
            for(Rule myRule : nt.getRules()){
                StringBuffer ruleStringBuffer = new StringBuffer();
                ruleStringBuffer.append(nt.getName()).append(' '); 
                //make a string out of RHS of rule
                for ( Constituent myConstituent : myRule.getRightHandSide()) {
                    if (myConstituent==null) System.out.println("NullpointerException in Rule: "+ myRule.getLeftHandSide().getName() + "; RHSsize="+ myRule.getRightHandSide().size());
                    else ruleStringBuffer.append(myConstituent.getName()).append(' ');                   
                }
                
                if (Main.GRAMMAR_PRINTING_FORMAT ==3) { //rules plus probabilities
                    //XXX
                    //NumberFormat numberFormatter;
                    //numberFormatter = NumberFormat.getNumberInstance();
                    ruleStringBuffer.append("#").append(myRule.getRuleProbability());
                }
                if (Main.GRAMMAR_PRINTING_FORMAT ==4) { //rules plus counts
                    ruleStringBuffer.append("#").append(myRule.getCount());
                }
                String ruleString = ruleStringBuffer.toString();
            
                
                  out.write(ruleString);  
                  out.newLine();              
            }    
        }         
        out.flush();
        out.close();
         }
        catch (IOException e)    {  System.out.println("ging mis");  }
    }
    
    public static void printCFGGrammar(HashMap<String, HashMap<String, Integer>> rulesForPrinting, HashMap<String, Integer> preterminalRulesForPrinting, HashSet<String> terminalsForPrinting) throws IOException
    {
        //write CFG rules + counts to file
    	BufferedWriter out = new BufferedWriter(new FileWriter(Main.OUTPUT_DIR + "/" + "CFG_Grammar.txt"));

        //printing format=4: only rules + counts (for reading in Stolcke)
        if (Main.GRAMMAR_PRINTING_FORMAT==4)    {
            //enumerate nonT
            for (String myNonT : rulesForPrinting.keySet()) {
                //enumerate rules of nonT
                for (String myRule : rulesForPrinting.get(myNonT).keySet()) {
                    //write key(=rule) + "#" + value(=count)
                    out.write(myRule + "#" + rulesForPrinting.get(myNonT).get(myRule).intValue());
                    out.newLine();
                }
            }
            //preterminal rules
            for (String myRule : preterminalRulesForPrinting.keySet()) {
                    //write key(=rule) + "#" + value(=count)
                    out.write(myRule + "#" + preterminalRulesForPrinting.get(myRule).intValue());
                    out.newLine();
                }
            
        }
        //CFG-grammar output in format for reading it back into GoodmanDop
        if (Main.GRAMMAR_PRINTING_FORMAT==1)    {
            //format=1: print terminals, nonT, and rules+probabilities
            //WSJ: nonTerminals are all of them; terminals are Node.type=terminal to lowercase
            //if (myNode.getType()==Main.TERMINAL)
            
           out.write("TERMINALS");
           out.newLine();
           if (Main.GRAMMAR_PRINTING_PRETERMINALS) {
               for (String myRule : preterminalRulesForPrinting.keySet()) {
                   //preterminalRule = myNodeName + " " + myNodeName.toLowerCase() + " ";
                    out.write(myRule.split(" ")[1]);    //lowerCase
                    out.newLine();
               }
           }
           else {
               for (String myTerminal : terminalsForPrinting) {
                    out.write(myTerminal.toLowerCase());    //lowerCase
                    out.newLine();
               }
           }
           
           out.write("NONTERMINALS");
           out.newLine();
            for (String myNonT : rulesForPrinting.keySet()) {
                out.write(myNonT);
                out.newLine();
           }
           //preterminals are also nonT
            if (Main.GRAMMAR_PRINTING_PRETERMINALS) {
               for (String myRule : preterminalRulesForPrinting.keySet()) {
                    //preterminalRule = myNodeName + " " + myNodeName.toLowerCase() + " ";
                    out.write(myRule.split(" ")[0]);
                    out.newLine();
               }
            }
            out.write("PRODUCTION RULES");
            out.newLine();
   
            // myGrammar.storeRulesAccordingToRHS(true, out);
            //format: RULESOFNONTERMINAL " + nonT
            //RHS1*RHS2*RHS3*#probability

            for (String myNonT : rulesForPrinting.keySet()) {
                
                out.write("RULESOFNONTERMINAL " + myNonT);
                out.newLine();
                //calculate totalFreq of rule
                int totalFreq=0;
                double ruleProb = 0d;
                for (String myRuleString : rulesForPrinting.get(myNonT).keySet()) {
                    totalFreq += rulesForPrinting.get(myNonT).get(myRuleString).intValue();
                }
                //enumerate rules of nonT
                for (String myRuleString : rulesForPrinting.get(myNonT).keySet()) {
                    //convert ruleString from format LHS RHS1 RHS2 etc to RHS1*RHS2* (w/o LHS)
                    String[] splitRule = myRuleString.split(" ");
                    StringBuffer rhsStringBuffer = new StringBuffer();
                    for (int i=1; i<splitRule.length; i++){
                        rhsStringBuffer.append(splitRule[i] + "*");
                    }
                    ruleProb = ((double) rulesForPrinting.get(myNonT).get(myRuleString).intValue())/((double) totalFreq);
                    rhsStringBuffer.append("#" + ruleProb);
           
                    out.write(rhsStringBuffer.toString());
                    out.newLine();
                }
            }
        
     
            //idemdito voor preterminal rules
            if (Main.GRAMMAR_PRINTING_PRETERMINALS) {
                for (String myRule : preterminalRulesForPrinting.keySet()) {
                    out.write("RULESOFNONTERMINAL " + myRule.split(" ")[0]);
                    out.newLine();
                   //preterminalRule = myNodeName + " " + myNodeName.toLowerCase() + " ";
                    out.write(myRule.split(" ")[1] + "*#1.");    //lowerCase
                    out.newLine();   
                }
            }
        
        }
        out.flush();
        out.close();
    }
    
    public static void printSentences(ArrayList<String> mySentences, String outputfile) throws IOException {
        //write unlabeled text to file
    	BufferedWriter out = new BufferedWriter(new FileWriter(Main.OUTPUT_DIR + "/" + outputfile));

        for (String mySentence : mySentences) {
            out.write(mySentence);
            out.newLine();
        }
        out.flush();
        out.close();
    }
    
    public void printStuff(parseTree computedParse, parseTree givenParse, String firstParseName, String secondParseName) throws IOException {
        //computedParse=Stolcke  givenParse=treebank
        //printToLatex(boolean blnPrintNrSubtrees, boolean blnPrintNodeSpans
        //temp
        String computedParseLatex, givenParseLatex;
        if (!Main.DO_RIGHT_BRANCHING_TEST ) computedParseLatex = computedParse.printToLatex(false, true, firstParseName);    
        if (Main.PRINT_STANDARD_OUTPUT_TO_FILE) {
            out_complete.write("The " + firstParseName + " parse tree is: " + computedParseLatex);    //.substring(15)
            out_complete.newLine();
        }
        if (Main.PRINT_COMPUTED_PARSES) {
        	if (Main.BRACKET_FORMAT_WSJ_STYLE) {	
        		out_parses.write(computedParse.printWSJFormat());
        		out_parses.newLine();
	        }
	        else {
	        	boolean blnWithUnderScore = false;
	            out_parses.write(computedParse.printOVISFormat(blnWithUnderScore));
	            out_parses.newLine();
	        }
        }
        //treebank parse
        if (!Main.DO_PARSING_NO_EVALUATION) givenParseLatex = givenParse.printToLatex(false, true, secondParseName);
        if (Main.PRINT_STANDARD_OUTPUT_TO_FILE) {
            out_complete.write("The " + secondParseName + " parse tree is: " + givenParseLatex);  //.substring(15)
            out_complete.newLine();
        }
        if (!Main.DO_RIGHT_BRANCHING_TEST && !Main.DO_PARSING_NO_EVALUATION ) {
            String cparse = computedParse.printSimple(false, true, "c");
            if (Main.PRINT_STANDARD_OUTPUT_TO_FILE) printLineToStandardFile(cparse);
        }
        if (!Main.DO_PARSING_NO_EVALUATION) {
            String gparse = givenParse.printSimple(false, true, "m");
            if (Main.PRINT_STANDARD_OUTPUT_TO_FILE) printLineToStandardFile(gparse);
        }

    }
    
    /*
    public void  printLineConditional(String myLine) throws IOException  {
    	
    	
    	if (Main.PRINT_COMPUTED_PARSES) {
    		out_parses.write(myLine);
    		out_parses.newLine();
    	}
    }
    */
    
     public void  printLineToStandardFile(String myLine) throws IOException  {
    	
    		out_complete.write(myLine);
    		out_complete.newLine();
    }
     
    
            
    public void flushAndClose() throws IOException {
    	if (Main.PRINT_STANDARD_OUTPUT_TO_FILE) {
            out_complete.flush();
            out_complete.close();
        }
        if (Main.PRINT_COMPUTED_PARSES) {
            out_parses.flush();
            out_parses.close();
        }
    }
}
