/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.hadoop.examples.pi;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.hadoop.examples.pi.math.Bellard;
import org.apache.hadoop.examples.pi.math.Bellard.Parameter;

/** A class for parsing outputs */
public final class Parser {
  static final String VERBOSE_PROPERTY = "pi.parser.verbose";

  final boolean isVerbose;
  
  public Parser(boolean isVerbose) {
    this.isVerbose = isVerbose;
  }
  
  private void println(String s) {
    if (isVerbose)
      Util.out.println(s);
  }

  /** Parse a line */
  private static void parseLine(final String line, Map<Parameter, List<TaskResult>> m) {
//      LOG.info("line = " + line);
    final Map.Entry<String, TaskResult> e = DistSum.string2TaskResult(line);
    if (e != null) {
      final List<TaskResult> sums = m.get(Parameter.get(e.getKey()));
      if (sums == null)
        throw new IllegalArgumentException("sums == null, line=" + line + ", e=" + e);
      sums.add(e.getValue());
    }
  }

  /** Parse a file or a directory tree */
  private void parse(File f, Map<Parameter, List<TaskResult>> sums) throws IOException {
    if (f.isDirectory()) {
      println("Process directory " + f);
      for(File child : f.listFiles())
        parse(child, sums);
    } else if (f.getName().endsWith(".txt")) {
      println("Parse file " + f);
      final Map<Parameter, List<TaskResult>> m = new TreeMap<Parameter, List<TaskResult>>();    
      for(Parameter p : Parameter.values())
        m.put(p, new ArrayList<TaskResult>());

      final BufferedReader in = new BufferedReader(new FileReader(f)); 
      try {
        for(String line; (line = in.readLine()) != null; )
          try {
            parseLine(line, m);
          } catch(RuntimeException e) {
            Util.err.println("line = " + line);
            throw e;
          }
      } finally {
        in.close();
      }

      for(Parameter p : Parameter.values()) {
        final List<TaskResult> combined = Util.combine(m.get(p));
        if (!combined.isEmpty()) {
          println(p + " (size=" + combined.size() + "):");
          for(TaskResult r : combined)
            println("  " + r);
        }
        sums.get(p).addAll(m.get(p));
      }
    }
  }

  /** Parse a path */
  private Map<Parameter, List<TaskResult>> parse(String f) throws IOException {
    final Map<Parameter, List<TaskResult>> m = new TreeMap<Parameter, List<TaskResult>>();
    for(Parameter p : Parameter.values())
      m.put(p, new ArrayList<TaskResult>());
    parse(new File(f), m);

    //LOG.info("m=" + m.toString().replace(", ", ",\n  "));
    for(Parameter p : Parameter.values())
      m.put(p, m.get(p));
    return m;
  }

  /** Parse input and re-write results. */
  Map<Parameter, List<TaskResult>> parse(String inputpath, String outputdir
      ) throws IOException {
    //parse input
    Util.out.print("\nParsing " + inputpath + " ... ");
    Util.out.flush();
    final Map<Parameter, List<TaskResult>> parsed = parse(inputpath);
    Util.out.println("DONE");

    //re-write the results
    if (outputdir != null) {
      Util.out.print("\nWriting to " + outputdir + " ...");
      Util.out.flush();
      for(Parameter p : Parameter.values()) {
        final List<TaskResult> results = parsed.get(p);
        Collections.sort(results);

        final PrintWriter out = new PrintWriter(
            new FileWriter(new File(outputdir, p + ".txt")), true);
        try {
          for(int i = 0; i < results.size(); i++)
            out.println(DistSum.taskResult2string(p + "." + i, results.get(i)));
        }
        finally {
          out.close();
        }
      }
      Util.out.println("DONE");
    }
    return parsed;
  }

  /** Combine results */
  static <T extends Combinable<T>> Map<Parameter, T> combine(Map<Parameter, List<T>> m) {
    final Map<Parameter, T> combined = new TreeMap<Parameter, T>();
    for(Parameter p : Parameter.values()) {
      final List<T> results = Util.combine(m.get(p));
      Util.out.format("%-6s => ", p); 
      if (results == null)
        Util.out.println("null");
      else if (results.size() != 1) 
        Util.out.println(results.toString().replace(", ", ",\n           "));
      else {
        final T r = results.get(0);
        combined.put(p, r); 
        Util.out.println(r);
      }
    }
    return combined;
  }

  /** main */
  public static void main(String[] args) throws IOException {
    if (args.length < 2 || args.length > 3)
      Util.printUsage(args, Parser.class.getName()
          + " <b> <inputpath> [<outputdir>]");

    int i = 0;
    final long b = Util.string2long(args[i++]);
    final String inputpath = args[i++];
    final String outputdir = args.length >= 3? args[i++]: null;

    //read input
    final Map<Parameter, List<TaskResult>> parsed = new Parser(true).parse(inputpath, outputdir);
    final Map<Parameter, TaskResult> combined = combine(parsed);
    long duration = 0;
    for(TaskResult r : combined.values())
      duration += r.getDuration();

    //print pi
    final double pi = Bellard.computePi(b, combined);
    Util.printBitSkipped(b);
    Util.out.println(Util.pi2string(pi, Bellard.bit2terms(b)));
    Util.out.println("cpu time = " + Util.millis2String(duration));
  }
}
