/**********************************************
 *  AOSD 10 Submission Files                  *
 *  Timings.java :                            *
 *    Runs performance tests for Pict based   *
 *    functions                               *
 *                                            *
 *********************************************/

import edu.neu.ccs.demeterf.lib.*;
import edu.neu.ccs.demeterf.*;

public class Timings{
    static void p(String s){ System.out.println(s); }
    public static void main(String[] args) throws Exception{
        List<String> 
            funcs = List.create("circstu","tosvg","scale","circ2sqr","flip","compress"),
            names = List.create("Hand","Vis","Inln","Par","Reflect");

        if(args.length < 2 || funcs.index(args[0]) < 0){
            p(" usage: java Timings <function:Str> <type:int>");
            return;
        }
        
        Fact f = factory(funcs.index(args[0].toLowerCase()));

        //Pict p = Pict.kspiral(args.length >= 3?Integer.parseInt(args[2]):100);
        Pict p = Pict.design(args.length >= 3?Integer.parseInt(args[2]):120);
        int thresh = args.length >= 4?Integer.parseInt(args[3]):50;
        System.gc();
        int which = Integer.parseInt(args[1]);
        Object o = null;
        long st = System.currentTimeMillis();
        switch(which){
        case 0:o = f.hand(p);break;
        case 1:o = f.vist(p);break;
        case 2:o = f.inln(p);break;
        case 3:o = f.par(p,thresh);break;
        case 4:o = f.refl(p);break;
        }
        long fin = (System.currentTimeMillis()-st);
        p(args[0]+"["+names.lookup(which)+":"+p.size()+"]: "+fin);
    }

    static Fact factory(int f){
        switch(f){
        case 0:return new CircsTUF();
        case 1:return new ToSVGF();
        case 2:return new ScaleF();
        case 3:return new Circ2SqrF();
        case 4:return new FlipF();
        case 5:return new ComprF();
        case 6:return new ToStrF();
        }
        return null;
    }
}

abstract class Fact{
    abstract Object hand(Pict p);
    abstract Object vist(Pict p);
    abstract Object inln(Pict p);
    abstract Object par(Pict p, int thresh);
    abstract Object refl(Pict p);
}

class CircsTUF extends Fact{
    Object hand(Pict p){ return p.circles(); }
    Object vist(Pict p){ return p.accept(new CircsVis()); }
    Object inln(Pict p){ return new InlineCircsTU(new CircsTU()).traverse(p); }
    Object par(Pict p, int thresh){ return new InlineParCircsTU(new CircsTU(),thresh).traverse(p); }
    Object refl(Pict p){ return new Traversal(new CircsTU()).traverse(p); }
}

class ToSVGF extends Fact{
    static Ctx ctx = new Ctx(200,200);
    Object hand(Pict p){ return p.toSVG(ctx); }
    Object vist(Pict p){ return p.accept(new ToSVGVis(ctx)); }
    Object inln(Pict p){ return new InlineToSVG(new ToSVG()).traverse(p,ctx); }
    Object par(Pict p, int thresh){ return new InlineParToSVG(new ToSVG(),thresh).traverse(p,ctx); }
    Object refl(Pict p){ return new Traversal(new ToSVG()).traverse(p,ctx); }
}

class ScaleF extends Fact{
    Object hand(Pict p){ return p.scale(2); }
    Object vist(Pict p){ return p.accept(new ScaleVis(2)); }
    Object inln(Pict p){ return new InlineScale(new Scale(2)).traverse(p); }
    Object par(Pict p, int thresh){ return new InlineParScale(new Scale(2),thresh).traverse(p); }
    Object refl(Pict p){ return new Traversal(new Scale(2)).traverse(p); }
}

class Circ2SqrF extends Fact{
    Object hand(Pict p){ return p.circ2sqr(); }
    Object vist(Pict p){ return p.accept(new Circ2SqrVis()); }
    Object inln(Pict p){ return new InlineCirc2Sqr(new Circ2Sqr()).traverse(p); }
    Object par(Pict p, int thresh){ return new InlineParCirc2Sqr(new Circ2Sqr(),thresh).traverse(p); }
    Object refl(Pict p){ return new Traversal(new Circ2Sqr()).traverse(p); }
}

class FlipF extends Fact{
    Object hand(Pict p){ return p.flip(); }
    Object vist(Pict p){ return p.accept(new FlipVis()); }
    Object inln(Pict p){ return new InlineFlip(new Flip()).traverse(p); }
    Object par(Pict p, int thresh){ return new InlineParFlip(new Flip(),thresh).traverse(p); }
    Object refl(Pict p){ return new Traversal(new Flip()).traverse(p); }
}

class ComprF extends Fact{
    Object hand(Pict p){ return p.flip(); }
    Object vist(Pict p){ return p.accept(new ComprVis()); }
    Object inln(Pict p){ return new InlineCompress(new Compress()).traverse(p); }
    Object par(Pict p, int thresh){ return new InlineParCompress(new Compress(),thresh).traverse(p); }
    Object refl(Pict p){ return new Traversal(new Compress()).traverse(p); }
}

class ToStrF extends Fact{
    Object hand(Pict p){ return p.toString(); }
    Object vist(Pict p){ return p.accept(new ToStringVis()); }
    Object inln(Pict p){ return new InlineToString(new ToString()).traverse(p); }
    Object par(Pict p, int thresh){ return new InlineParToString(new ToString(),thresh).traverse(p); }
    Object refl(Pict p){ return new Traversal(new ToString()).traverse(p); }
}