package dxg;

import java.util.ArrayList;
import java.io.*;
import java.nio.*;
import vfs.Vfs;

/**
 * モデルデータを格納したdxgファイルを表すクラス
 */
public class Dxg {
    ArrayList<Span> ranges;

    FileHeader file_header;
    GroupData[] group_list;
    AuxA auxA;
    AuxB auxB;
    AuxC auxC;
    AuxD auxD;

    public static final int SPANS = 0;
    public static final int FLAGS = 1;
    public static final int OFFSETS = 2;
    public static final int SIZES = 3;
    public static final int NAMES = 4;

    public Dxg(Vfs vfs, String relPath) throws DxgException {
	ByteBuffer bf = null;
	try {
	    bf = vfs.getBuffer(relPath);
	} catch (IOException e) {
	    throw new DxgException("cannot get buffer from " + relPath, e);
	}
	ranges = new ArrayList<Span>();
	ranges.add(new Span("ファイル", 0, bf.capacity(), 1, bf.capacity()));

	// ファイルヘッダ部
	file_header = new FileHeader(bf, ranges);

	// メッシュデータ部
	switch(file_header.flag_a3 & 3) {
	case 1:
	case 3:
	    group_list = new GroupData[file_header.nr_groups];
	    for(int n = 0; n < file_header.nr_groups; n++)
		group_list[n] = new GroupData(bf, n, ranges);
	    auxA = null;
	    break;

	case 2:
	    group_list = new GroupData[0];
	    auxA = new AuxA(bf, "a0", file_header, ranges);
	    break;

	default:
	    throw new DxgException("illegal value: unexpected flag_a3");
	}

	// 不明1
	int exptected = file_header.next_data_offset + 20;
	if(exptected < bf.position())
	    throw new DxgException("illegal value: next_data_offset");
	if(exptected > bf.position()) {
	    ranges.add(new Span("不明1", bf.position(),
				exptected - bf.position(),
				1, exptected - bf.position()));
	    bf.position(exptected);
	}

	// 補助データ部
	if((file_header.flag_a3 & 3) == 3)
	    auxA = new AuxA(bf, "a1", file_header, ranges);
	auxB = null; auxC = null; auxD = null;
	if((file_header.flag_a3 & 4) == 4)
	    auxB = new AuxB(bf, "b", file_header, ranges);
	if((file_header.flag_a3 & 8) == 8)
	    auxC = new AuxC(bf, "c", file_header, ranges);
	if((file_header.flag_a3 & 32) == 32)
	    auxD = new AuxD(bf, "d", file_header, ranges);

	// 不明3
	exptected = bf.capacity();
	if(exptected > bf.position()) {
	    ranges.add(new Span("不明3", bf.position(),
				exptected - bf.position(),
				1, exptected - bf.position()));
	}
    }

    public void show(int what) {
	if(what == SPANS) {
	    Span.list(ranges);
	} else {
	    file_header.show(what);
	    for(GroupData x: group_list)
		x.show(what);
	    if(auxA != null) auxA.show(what);
	    if(auxB != null) auxB.show(what);
	    if(auxC != null) auxC.show(what);
	    if(auxD != null) auxD.show(what);
	}
    }

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

    public int getGroupId(String groupName) {
	for(int i = 0; i < file_header.group_names.length; i++)
	    if(file_header.group_names[i].equals(groupName))
		return i;
	return -1;
    }

    public GroupData[] getGroups() {
	return group_list;
    }
}
