package jp.hasc.hasctool.ui.views.beanslist;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Comparator;

import jp.hasc.hasctool.core.runtime.RuntimeBean;
import jp.hasc.hasctool.core.runtime.RuntimeContext;

import com.thoughtworks.xstream.XStream;

/**
 * @author iwasaki
 */
public class BeansListGenerator {
	public static void main(String[] args) throws IOException {
		new BeansListGenerator().run(args);
	}
	
	private BeansFolder rootFolder_;
	
	private void run(String[] args) throws IOException {
		File cp=null;
		String pkg="";
		String fname=null;
		for(int i=0;i<args.length;++i) {
			String arg=args[i];
			if (arg.equals("-dir")) {
				cp=new File(args[++i]);
			}else if (args.equals("-pkg")) {
				pkg=args[++i];
			}else if (arg.equals("-o")) {
				fname=args[++i];
			}else{
				System.err.println("Invalid argument: "+arg);
				System.exit(1);
			}
		}
		if (cp==null) {
			System.err.println("Arguments Required: -dir (class directory) [-o (output file)] [-pkg (target package)]");
			System.exit(1);
		}
		//
		rootFolder_=new BeansFolder("");
		Writer out=new OutputStreamWriter((fname==null?System.out:new FileOutputStream(fname)), RuntimeContext.DEFAULT_CHARSET);
		processPackage(new File(cp, pkg.replace('.', '/')), pkg);
		XStream xs = BeansListLoader.newXStream();
		xs.toXML(rootFolder_.subFolders(), out);
		out.close();
	}

	private void processPackage(File path, String pkg) {
		BeansFolder fol=new BeansFolder(pkg);
		File[] li=path.listFiles();
		// sort
		Arrays.sort(li, new Comparator<File>() {
			@Override
			public int compare(File o1, File o2) {
				return o1.getName().toLowerCase().compareTo(o2.getName().toLowerCase());
			}
		});
		for(File f:li) {
			if (f.isFile()) {
				String fname = f.getName();
				if (fname.endsWith(".java") || (fname.endsWith(".class") && !fname.contains("$"))) {
					String cname=fname.substring(0,fname.lastIndexOf('.'));
					try {
						Class<?> c = Class.forName(pkg.isEmpty()?cname:(pkg+"."+cname));
						if (RuntimeBean.class.isAssignableFrom(c) && !Modifier.isAbstract(c.getModifiers()) &&
								Modifier.isPublic(c.getModifiers()) && !c.isInterface() )
						{
							fol.classes().add(new BeanClass(c));
						}
					} catch (ClassNotFoundException ex) {
						System.err.println(ex.toString());
					}
				}
			}
		}
		if (!fol.classes().isEmpty()) {
			rootFolder_.subFolders().add(fol);
		}
		
		// sub directories
		for(File f:path.listFiles()) {
			if (f.isDirectory()) {
				String fname = f.getName();
				if (fname.startsWith(".")) continue;
				processPackage(f, pkg.isEmpty()?fname:(pkg+"."+fname));
			}
		}
	}
}
