package simpledb;

import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;

/**
 * Tuple maintains information about the contents of a tuple.
 * Tuples have a specified schema specified by a TupleDesc object and contain
 * Field objects with the data for each field.
 */
public class Tuple {
    private TupleDesc desc;
    private RecordID recordID;
    private List<Field> fields;

    public static Tuple combine(Tuple t1, Tuple t2) {
        TupleDesc td1 = t1.getTupleDesc();
        TupleDesc td2 = t2.getTupleDesc();
        
        Tuple r = new Tuple(TupleDesc.combine(td1, td2));

        int j = 0;

        for (int i = 0; i < td1.numFields(); i++, j++) {
            r.setField(j, t1.getField(i));
        }

        for (int i = 0; i < td2.numFields(); i++, j++) {
            r.setField(j, t2.getField(i));
        }

        return r;
    }
    
    /**
     * Constructor.
     * Create a new tuple with the specified schema (type).
     *
     * @param td The schema of this tuple.
     * @requires that td be a valid TupleDesc instance with at
     *   least one field.
     */
    public Tuple(TupleDesc td) {
        desc = td;
        recordID = null;
        fields = new ArrayList();

        for (int i = 0; i < td.numFields(); i++) {
            fields.add(null);
        }

    }
    
    /**
     * @return The TupleDesc representing the schema of this tuple.
     */
    public TupleDesc getTupleDesc() {
        return desc;
    }
    
    /**
     * @return The RecordID representing the location of this tuple on
     *   disk. May be null.
     */
    public RecordID getRecordID() {
        return recordID;
    }

    /**
     * @effects Set the RecordID information for this tuple.
     * @param rid The new RecordID of this tuple.
     */
    public void setRecordID(RecordID rid) {
        recordID = rid;
    }

    /**
     * Change the value of the ith field of this tuple.
     *
     * @param i The index of the field to change
     * @param f The value to change it to.
     * @requires i &gt;= 0 and i &lt; fields.length
     */
    public void setField(int i, Field f) {
        fields.set(i, f);
    }

    /**
     * Return the value of the ith field, or null if it has not been set.
     *
     * @requires i &gt;= 0 and i &lt; fields.length
     */
    public Field getField(int i) {
        return fields.get(i);
    }
    
    /**
     * Dumps the contents of this Tuple on standard out.
     * Note that to pass the grader.pl script, the format needs to be as
     * follows:
     * column1\tcolumn2\tcolumn3\t...\tcolumnN
     * column1\tcolumn2\tcolumn3\t...\tcolumnN
     * column1\tcolumn2\tcolumn3\t...\tcolumnN
     *
     * where \t is any whitespace, except newline.
     */
    public void print() {
        for (Iterator it = fields.iterator(); it.hasNext();) {
            Field f = (Field) it.next();
            System.out.print(f.toStr());
            System.out.print("\t");
        }
        System.out.print("\n");
    }
}
