import java.io.File;
import java.io.IOException;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.mapred.JobClient;
import org.apache.hadoop.mapred.JobConf;

public class MatrixMultDriver {

    /* Inputs: in-path-A in-path-B out-dir [mid-root] */
    public static void main(String[] args) {
	if (args.length < 3) {
	    System.out.println("Usage: MatrixMult <input A path> <input B path> <output path> [<mid path root>]");
	    System.exit(0);
	}
	String inApath = args[0];
	String inBpath = args[1];
	String outpath = args[2];
	String midroot = "mid";
	if (args.length > 3) 
	    midroot = args[3];
	String pinpath = midroot + "-in";
	String pmidpath = midroot + "-mid";
	try {
	    File fileA = new File(inApath);
	    Graph A = new Graph(fileA);
	    A.assignTags("A");
	    File dumpA = new File(pinpath, "A");
	    A.write(dumpA);
	} catch (IOException e) {
	    System.out.println("Can't process matrix A:");
	    System.out.println(e.toString());
	    return;
	}
	try {
	    File fileB = new File(inBpath);
	    Graph B = new Graph(fileB);
	    B.assignTags("B");
	    File dumpB = new File(pinpath, "B");
	    B.write(dumpB);
	} catch (IOException e) {
	    System.out.println("Can't process matrix B:");
	    System.out.println(e.toString());
	    return;
	}

	/* Phase 1 */
	JobConf conf1 = new JobConf(MatrixMultDriver.class);
	conf1.setJobName("MatrixMult");
	conf1.setMapOutputKeyClass(IntWritable.class);
	conf1.setMapOutputValueClass(Text.class);
	conf1.setOutputKeyClass(Text.class);
	conf1.setOutputValueClass(Text.class);
	conf1.setInputPath(new Path(pinpath));
	conf1.setOutputPath(new Path(pmidpath));
	conf1.setMapperClass(P1Mapper.class);
	conf1.setReducerClass(P1Reducer.class);

	/* Local execution */
	conf1.set("mapred.job.tracker", "local");
	try {
	    JobClient.runJob(conf1);
	} catch (Exception e) {
	    e.printStackTrace();
	}

	/* Phase 2 */
	JobConf conf2 = new JobConf(MatrixMultDriver.class);
	conf2.setJobName("MatrixMult");
	conf2.setMapOutputKeyClass(Text.class);
	conf2.setMapOutputValueClass(Text.class);
	conf2.setOutputKeyClass(Text.class);
	conf2.setOutputValueClass(Text.class);
	conf2.setInputPath(new Path(pmidpath));
	conf2.setOutputPath(new Path(outpath));
	conf2.setMapperClass(P2Mapper.class);
	conf2.setReducerClass(P2Reducer.class);
	/* Local execution */
	conf2.set("mapred.job.tracker", "local");
	try {
	    JobClient.runJob(conf2);
	} catch (Exception e) {
	    e.printStackTrace();
	}
    }
}
