package simpledb;
import java.util.*;

/**
 * TupleDesc describes the schema of a tuple.
 */
public class TupleDesc {
    private List<Type> fields;
    private int size;

    /**
     * Merge two TupleDescs into one, with td1.numFields + td2.numFields 
     * fields, with the first td1.numFields coming from td1 and the remaining 
     * from td2.
     * @param td1 The TupleDesc with the first fields of the new TupleDesc
     * @param td2 The TupleDesc with the last fields of the TupleDesc
     * @return the new TupleDesc
     */
    public static TupleDesc combine(TupleDesc td1, TupleDesc td2) {
        Type[] typeAr = new Type[td1.numFields() + td2.numFields()];
        int j = 0;

        for (int i = 0; i < td1.numFields(); i++, j++) {
            typeAr[j] = td1.getType(i);
        }

        for (int i = 0; i < td2.numFields(); i++, j++) {
            typeAr[j] = td2.getType(i);
        }

        return new TupleDesc(typeAr);
    }
    
    /**
     * Constructor.
     * Create a new tuple desc with typeAr.length fields with fields of the
     * specified types.
     *
     * @param typeAr array specifying the number of and types of fields in
     *        this TupleDesc
     * @requires that typeAr contain at least one entry
     */
    public TupleDesc(Type[] typeAr) {
	fields = new ArrayList<Type>();
        size = 0;

        for (int i = 0; i < typeAr.length; i++) {
            fields.add(typeAr[i]);
            size += typeAr[i].getLen();
        }
    }

    /**
     * @return the number of fields in this TupleDesc
     */
    public int numFields() {
        return fields.size();
    }

    /**
     * Gets the type of the ith field of this TupleDesc.
     *
     * @param i The index of the field to get the type of
     * @return the type of the ith field
     * @throws NoSuchElementException if i is not a valid field reference.
     * @requires that i is a valid field reference.
     */
    public Type getType(int i) throws NoSuchElementException {
        if ((i < 0) || i > fields.size()) {
            throw new NoSuchElementException();
        }

        return fields.get(i);
    }

    /**
     * @return The size (in bytes) of tuples corresponding to this TupleDesc.
     * Note that tuples from a given TupleDesc are of a fixed size.
     */
    public int getSize() {
        return size;
    }
    
    /**
     * Returns whether or not two TupleDesc are equal.
     * Two TupleDescs are considered equal if they are the same size and if the
     * n-th type in this TupleDesc is equal to the n-th type in td.
     *
     * @param td the TupleDesc instance against which we compare
     */
    public boolean equals(TupleDesc td) {
	return fields.equals(td.fields);
    }
}
