import java.io.*;
import java.util.*;

public class CategoryListBuilder {
    private String mBasePath;
    private int mPrefixLen;

    private static final int MAX_VARIATION = 20;
    private static final int PART_START = 1;
    private static final int PART_END = 16;

    public CategoryListBuilder(String basePath) {
	mBasePath = basePath;
	mPrefixLen = mBasePath.length() + 1;
    }

    public ArrayList<Category> buildList() {
	ArrayList<Category> catList = new ArrayList<Category>();

	catList.addAll(buildChara());
	catList.addAll(buildCharaParts());
	catList.addAll(buildItems());
	catList.addAll(buildFieldObjects());
	return catList;
    }

    //----------------------------------------------------------------------

    private File trim(File file) {
	String path = file.getPath();
	if(path.startsWith(mBasePath + File.separator))
	    return new File(path.substring(mPrefixLen));
	return file;
    }

    private File[] listSorted(File dir) {
	File[] array = dir.listFiles();
	Arrays.sort(array);
	return array;
    }

    private File[] findChara(File dir, String name1, int var) {
	int part;
	File[] r = new File[PART_END + 1];
	for(part = 0; part < PART_START; part++)
	    r[part] = null;
	for(part = PART_START; part <= PART_END; part++) {
	    String path = String.format("%s_0_%02d_%03d.vra", name1, part, var);
	    File file = new File(dir, path);
	    if(!file.exists()) {
		path = String.format("%s_1_%02d_%03d.vra", name1, part, var);
		file = new File(dir, path);
		if(!file.exists())
		    return null;
	    }
	    r[part] = trim(file);
	}
	return r;
    }

    ArrayList<Category> buildChara() {
	ArrayList<Category> catList = new ArrayList<Category>();
	Category c = new Category("キャラクタ");

	// unpacked/chara/A/BCDEF/attr/ABCDEF_x_yy_zzz.vra
	File baseDir = new File(mBasePath, "chara");
	for(File dirA: listSorted(baseDir)) {
	    for(File dirBcdef: listSorted(dirA)) {
		File dir = new File(dirBcdef, "attr");
		if(!dir.isDirectory())
		    continue;

		String name1 = dirA.getName() + dirBcdef.getName();
		for(int var = 0; var < MAX_VARIATION; var++) {
		    File files[] = findChara(dir, name1, var);
		    if(files != null)
			c.add(new CharaObj3D(name1, var, files));
		}
	    }
	}
	catList.add(c);
	return catList;
    }

    ArrayList<Category> buildCharaParts() {
	ArrayList<Category> catList = new ArrayList<Category>();

	// unpacked/chara/A/BCDEF/attr/ABCDEF_x_yy_zzz.vra
	File baseDir = new File(mBasePath, "chara");
	for(File dirA: listSorted(baseDir)) {
	    for(File dirBcdef: listSorted(dirA)) {
		Category c = new Category("キャラパーツ" + dirA.getName()
					  + dirBcdef.getName());
		File dir = new File(dirBcdef, "attr");
		if(!dir.isDirectory())
		    continue;
		for(File vra: listSorted(dir))
		    c.add(new CharaPartObj3D(vra.getName(), trim(vra)));
		catList.add(c);
	    }
	}
	return catList;
    }

    ArrayList<Category> buildItems() {
	ArrayList<Category> catList = new ArrayList<Category>();

	// unpacked/item/A/BC/DEFGH/attr/ABCDEFGH_n_n.vra
	File baseDir = new File(mBasePath, "item");
	for(File dirA: listSorted(baseDir)) {
	    if(dirA.getName().equals("icon"))
		continue;
	    for(File dirBc: listSorted(dirA)) {
		Category c = new Category("アイテム" + dirA.getName()
					  + dirBc.getName() + "xxxxx");

		for(File dirDefgh: listSorted(dirBc)) {
		    File dir = new File(dirDefgh, "attr");
		    if (!dir.isDirectory())
			continue;
		    for(File vra: listSorted(dir))
			c.add(new ItemObj3D(vra.getName(), trim(vra)));
		}

		catList.add(c);
	    }
	}
	return catList;
    }

    ArrayList<Category> buildFieldObjects() {
	ArrayList<Category> catList = new ArrayList<Category>();

	// unpacked/world/object/XX/attr/OZ_XX_yy_zzzzzzzz.vra
	File baseDir = new File(mBasePath, "world/object");
	for(File xxDir: listSorted(baseDir)) {
	    Category c = new Category("フィールドオブジェクト"
				      + xxDir.getName());
	    File dir = new File(xxDir, "attr");
	    if (!dir.isDirectory())
		continue;
	    for(File vra: listSorted(dir))
		c.add(new FieldObj3D(vra.getName(), trim(vra)));
	    catList.add(c);
	}
	return catList;
    }
}
