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

/** A quick test of the new "imperative" demfgen.lib.List Methods */
public class ListTest{
    java.util.Random r = new java.util.Random();
    public static void main(String[] args){
        if(args.length != 1){
            p(" usage: ListTest <length>");
            System.exit(1);
        }
        
        int len = Integer.parseInt(args[0]);
        new ListTest().main(len);
    }

    
    static class Even extends List.Pred<Integer>
    { public boolean huh(Integer i){ return ((i&1)==0); }}
    static class Odd extends List.Pred<Integer>
    { public boolean huh(Integer i){ return ((i&1)==1); }}
    static class LComp extends List.GComp<Integer, Long>{
        public boolean comp(Integer i, Long l){ return (int)i == l; }
    };
    void main(int len){
        List<Integer> lst = List.buildlist(new List.Build<Integer>(){
            public Integer build(int i){ return i; }
        }, len);
        int rand = r.nextInt(len);
        
        test("Length", lst.length() == len);
        print("Map-Add1",lst.map(new List.Map<Integer, Integer>(){
            public Integer map(Integer i){ return i+1; }
        }),len);
        print("Append-List",lst.append(List.create(len,len+1,len+2)),len);
        print("Append-Element",lst.append(len),len);
        print("Shuffle",lst.shuffle(),len);
        print("Shuffle",lst.shuffle(),len);
        test("Contains",lst.contains(len-1));
        test("ContainsG",lst.containsG((long)(len-1), new LComp()));
        test("Contains",lst.contains(rand));
        test("ContainsG",lst.containsG((long)(rand), new LComp())); 
        test("Contains",lst.contains(new Odd()));
        test("Contains",lst.contains(new Even()));
        test("ContainsAny",lst.containsAny(List.create(1,3,5)));
        test("ContainsAnyG",lst.containsAnyG(List.create(1L,3L,5L), new LComp())); 
        test("ContainsAny",!lst.containsAny(List.create(-1,-3,-5)));
        test("ContainsAnyG",!lst.containsAnyG(List.create(-1L,-3L,-5L), new LComp())); 
        test("ContainsAll-#t",lst.containsAll(List.create(1,3,5)));
        test("ContainsAllG-#t",lst.containsAllG(List.create(1L,3L,5L), new LComp())); 
        test("ContainsAll-#f",!lst.containsAll(List.create(-1,3,5)));
        test("ContainsAllG-#f",!lst.containsAllG(List.create(-1L,-3L,-5L), new LComp())); 
        test("Find",rand == lst.find(rand));
        test("FindG",rand == lst.findG((long)rand, new LComp()));
        print("Remove",lst.remove(rand),len);
        test("lookup-"+rand+":"+lst.lookup(rand),rand == lst.lookup(rand));
        test("lookup-0",0 == lst.lookup(0));
        print("toString",lst.toString(", ", ""),len);
        print("toString",lst.toString(":", " #"),len);
        //print("toString",lst.toString(Stringer<X> s),len);
        print("Filter-Odd",lst.filter(new Odd()),len);
        print("Filter-Even",lst.filter(new Even()),len);
        print("foldl:sum:"+len*(len-1)/2,lst.foldl(new List.Fold<Integer, Long>(){
            public Long fold(Integer i, Long l){ return i+l; }
        }, 0L),len);
        print("foldr:fact",lst.pop().foldr(new List.Fold<Integer, Long>(){
            public Long fold(Integer i, Long l){ return i*l; }
        }, 1L),len);
        print("add",lst.add(99, 3),len);
        print("remove",lst.remove(3),len);
        print("sort",List.<Integer>create(2,3,1,5,2,65,26,34,27,1).sort(new List.Comp<Integer>(){
            public boolean comp(Integer a, Integer b){ return a < b; }
        }),len);
        print("zip",lst.zip(new List.Zip<Integer,Integer,String>(){
            public String zip(Integer a, Integer b){ return ""+a+":"+b; }
        }, List.create(9,8,7,6,5,4,3,2,1,0)),len);
        print("replace",List.<Long>create(1L,2L,3L,4L,5L,6L).replace(4, 99L),len);
        print("replace",List.<Long>create(1L,2L,3L,4L,5L,6L).replace(3L, 99L),len);
        print("replaceAll",List.<Long>create(1L,2L,3L,3L,2L,1L).replaceAll(2L, 99L),len);
        
        p("\n ** Total: "+total+"  Failed: "+fails+"\n");
    }
    
    void print(String s, Object lst, int len){
        if(len <= 20)
            p(extend(s,20)+" : "+lst);
    }
    String extend(String s, int i){
        if(s.length() < i)return extend(" "+s,i);
        return s;
    }
    
    int fails = 0, total = 0;
    public static void p(String s){ System.out.println(s); }
    public void test(String msg, boolean good){
        total++;
        if(!good){
            p(" !! Test #"+total+" Failed \""+msg+"\"\n");
            fails++;
        }
    }
}