package sandbox;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.io.StringReader;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.security.Security;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Properties;


import Sequenic.T2ext.CoverageEngine.SemiExhaustiveEngine;
import Sequenic.T2ext.Instrumenter.CFG;
import Sequenic.T2ext.Instrumenter.CFGBunchFile;

import sandbox.changeset.ChangeSet;
import sandbox.changeset.ClassFilesConcurrent;
import sandbox.changeset.Status;

/**
 * The sandbox contains classes in a very early stage of development. 
 * I.e. exploration and testing.
 * Once they reach a certain quality they will be moved into a proper package. 
 * 
 * This file is just a random collection of temporary test methods.
 * The purpose is to test other classes, both in and out of the sandbox.
 * E.g. how does java.util.Foo work, or what does T2ext.instrument() return, etc.
 * 
 * @author jeiels
 *
 */

@SuppressWarnings("unused")
public final class Main {
	
	private static final PrintStream o = System.out;
	private static void p(String... s){
		for(String x : s)
			o.print(x);
		o.println();
	}
	private static void pln(String... s){
		for(String x : s)
			o.println(x);
	}	
	
	private static void varargs(String... s){
		if(s==null)
			p("Null");
		else if(s.length==0)
			p("Length is 0");
	}	
	
	private static void main(final long startTime){
//		Sequenic.T2ext.Instrumenter.InjectionSimpleExample.main(null);
//		
//		for(CFG g : CFGBunchFile.load("TestCase.cfgs").cfgs){
//			p(g.toString());
//		}
		
		//tryT2();
		//compareLucene();
	}
	
	public static void main(String[] args) {
		long startTime = System.currentTimeMillis();
		main(startTime);
		startTime = System.currentTimeMillis()-startTime;
		try {
			assert false;
			System.out.println("ASSERTIONS ARE DISABED!!!!");
			System.out.println("PLEASE ENABLE THEM!!!");
		} catch (AssertionError e) { 
			System.out.println("Time taken: " + startTime+"ms  (assertions are enabled)"); 
		}

	}	

/*	Lucene. requires ant. Note: Lucene merged with Solr. Only use revisions <926576
	Note: luceneVeryOld = rev854000, luceneOld = rev924000, luceneNew = rev926576

e.g.    svn export -r 926576 http://svn.apache.org/repos/asf/lucene/java/trunk luceneNew
	    ant       // Nothing more is needed to build. class files are in build/classes/java
*/	
		private static final File luceneVeryOld = new File("loc/luceneVeryOld/build/classes/java");
		private static final File luceneOld = new File("loc/luceneOld/build/classes/java");
		private static final File luceneNew = new File("loc/luceneNew/build/classes/java");	
	
	private static void compareLucene(){
		ChangeSet cs = new ClassFilesConcurrent(luceneOld, luceneNew).getResults();
		new ClassFilesConcurrent(luceneVeryOld, luceneNew).getResults().printTo(o);
		cs.printTo(o, Status.defaultOrder());
	}
	
	private static void byteBufferTest() {
		// Example of how a bytebuffer works
		ByteBuffer bb = ByteBuffer.allocate(8);
		ByteBuffer bc = ByteBuffer.allocate(8);
		System.out.println("Remaining: "+bb.remaining() + " / " + bc.remaining() + " Compare: " + bb.compareTo(bc) + " / " + bc.compareTo(bb));
		bb.put(Byte.MAX_VALUE); bc.put(Byte.MIN_VALUE);
		System.out.println("Remaining: "+bb.remaining() + " / " + bc.remaining() + " Compare: " + bb.compareTo(bc) + " / " + bc.compareTo(bb));
		bb.flip(); bc.flip();
		System.out.println("Remaining: "+bb.remaining() + " / " + bc.remaining() + " Compare: " + bb.compareTo(bc) + " / " + bc.compareTo(bb));
		bb.clear(); bc.clear(); //bc.put(Byte.MAX_VALUE);
		System.out.println("Remaining: "+bb.remaining() + " / " + bc.remaining() + " Compare: " + bb.compareTo(bc) + " / " + bc.compareTo(bb));
		bb.flip(); bc.flip();
		System.out.println("Remaining: "+bb.remaining() + " / " + bc.remaining() + " Compare: " + bb.compareTo(bc) + " / " + bc.compareTo(bb));
		bb.clear(); bc.clear(); 
		System.out.println("Remaining: "+bb.remaining() + " / " + bc.remaining() + " Compare: " + bb.compareTo(bc) + " / " + bc.compareTo(bb));
	}


	public static void printPackages(URL pathOld, URL pathNew){
		URLClassLoader ucl0 = new URLClassLoader(new URL[]{pathOld});
		URLClassLoader ucl1 = new URLClassLoader(new URL[]{pathNew});
		
		try {
			ucl0.loadClass("simp.EqObject");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		Thread th = new Thread(){ 
			//this is a new anonymous innerclass, i.e. a class with no name.
			//It is a subclass of Thread, with run() overwritten. th is an instance of this class.
			//After compilation we have two files: ChangeSet.class and ChangeSet$1.class
			//This class is the second file.
			public void run(){
				System.out.println(Package.getPackage("simp") == null);
				for (Package p : Package.getPackages()) {
					System.out.println(p.getName());
				}
			}	
		};
		th.setContextClassLoader(ucl0);
		th.run();
	}


	public static void printPackages(){
		try {
			System.out.println(new File("loc/changeset/bin0/").toURI().toURL().toString());
			
			printPackages(new File("loc/changeset/bin0/").toURI().toURL(), 
					new File("loc/changeset/bin0/").toURI().toURL());
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
	}
	
	
	
	public static void tryT2(){
		Properties p = new Properties();		
		ChangeSet cs = new ClassFilesConcurrent(luceneOld, luceneNew).getResults();
		cs.printTo(o);	
		File wd = new File("loc/T2working_dir/");
		try {
			WrapperT2 wt2 = new WrapperT2("../luceneOldT2/",wd);
			int x = 0;
			for(String cl : cs.getClasses(Status.setExcl(Status.NEW))){
				String result = wt2.testComplete(cl).toString();
				String shortResult = WrapperT2.commonCause(result);
				if(shortResult!=null && shortResult.contains("java.security")){
					p("\nSECURITY!-- "+cl+"\n"+result+"\n");
				} else
					o.print((x%100==0?"\n"+x/100:"."));
//				if(shortResult==null)
//					p("!--"+cl);
//				else if(shortResult.contains("java.security")){
//					p("SECURITY!--"+cl);
//				} else
//					p("   (common) "+cl);
//				if(shortResult==null)
//					p("==="+cl+":\n"+result+"\n=========");
//				p("==="+cl+":");
//				p( shortResult==null? result+"\n=============" : shortResult);
//				p();
				if(++x>5000) break;
			}
			wt2.close();
		} catch (Exception e) {
			throw new Error(e);
		}
		p("Files in working directory:");
		p(wd.list());
	}
	
	public static void javaSort(){
		int[] a = new int[5];
		a[3] = 42;
		String[] b = new String[5];
		b[3] = "hey";
		Arrays.sort(a);
		//Arrays.sort(b);
		pln(Arrays.toString(a), Arrays.toString(b), Arrays.deepToString(b));		
	}
	
	public static void enums(){
		for(Status s: Status.values()){
			p(s.name(),String.valueOf(s.ordinal()),s.toString());
		}
	}
	
	public static class StaticInnerClass{
		public static boolean getNot(boolean b){
			return !b;
		}
	}
	
	public enum InnerEnum{
		GOOD, BAD
	}
	
	public interface InnerInterface{
		public void getNot();
	}

}