package vra;

import java.util.regex.*;

/**
 * vraノードの属性を表わすクラス
 */
public class Attr {
    private final static Pattern ATTR_REGEX = Pattern.compile
	("\\s*\\((\\w+)\\s+(\\w+)\\[(\\d+)\\]\\s+(.*)\\)");
    private final static Pattern COMMA_REGEX = Pattern.compile("\\s*,\\s*");

    private final static boolean DEBUG = false;

    private final String mName;
    private final String mType;
    private final Object[] mValues;

    /**
     * コンストラクタ.
     * フィールド値のみ設定。
     * VraAttrクラスはファクトリメソッド以外ではインスタンスを作らない。
     */
    private Attr(String name, String type, Object[] values) {
	mName = name;
	mType = type;
	mValues = values;
    }

    public String getName() {
	return mName;
    }

    public String getType() {
	return mType;
    }

    public Object[] getValues() {
	return mValues;
    }

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

    /**
     * 属性を表わす文字列からVraAttrオブジェクトを作成する。
     */
    public static Attr parse(String s) throws VraException {
	// まずは正規表現にマッチさせる
	Matcher m = ATTR_REGEX.matcher(s);
	if(!m.matches())
	    throw new VraException("illegal format: invalid input: " + s);
	String name = m.group(1);
	String baseType = m.group(2);
	int nrVectors = Integer.valueOf(m.group(3));
	int nrScalars = nrVectors;
	if(baseType.equals("vector3"))
	    nrScalars = nrVectors * 3;
	else if(baseType.equals("quat"))
	    nrScalars = nrVectors * 4;
	if(DEBUG)
	    System.out.printf("  attr: %s -> (%s %s[%d] %s)\n",
			      s, name, baseType, nrScalars, m.group(4));

	// カンマで分離
	String[] args = COMMA_REGEX.split(m.group(4), nrScalars);
	Object[] values = new Object[nrScalars];
	if(DEBUG)
	    for(int i = 0; i < args.length; i++)
		System.out.printf("  attr: args[%d]=%s\n", i, args[i]);

	// 値をそれぞれの型に整形
	if(baseType.equals("int32")
	   || baseType.equals("int16")
	   || baseType.equals("int8")) {
	    for(int i = 0; i < nrScalars; i++)
		values[i] = new Integer(Integer.valueOf(args[i]));
	} else if(baseType.equals("float")
		  || baseType.equals("vector3")
		  || baseType.equals("quat")) {
	    for(int i = 0; i < nrScalars; i++)
		values[i] = new Float(Float.valueOf(args[i]));
	} else if(baseType.equals("string")) {
	    for(int i = 0; i < nrScalars; i++)
		values[i] = args[i].substring(1, args[i].length() - 1);
	} else {
	    throw new VraException("illegal format: unknown type: " + baseType);
	}

	return new Attr(name, baseType, values);
    }

}
