/*
 Copyright 2004-2008 Paul R. Holser, Jr.  All rights reserved.
 Licensed under the Academic Free License version 3.0
 */

package joptsimple.internal;

import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
 * <p>A means to display data in a text grid.</p>
 *
 * @since 2.1
 * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
 * @version $Id: ColumnarData.java,v 1.2 2008/04/10 19:41:56 pholser Exp $
 */
public class ColumnarData {
    private static final String LINE_SEPARATOR = System.getProperty( "line.separator" );
    private final List columns = new LinkedList();
    private final String[] headers;

    /**
     * Creates a new grid with the given column headers.
     *
     * @param headers column headers
     */
    public ColumnarData( String[] headers ) {
        this.headers = (String[]) headers.clone();

        clear();
    }

    /**
     * Adds a row to the grid.  The data will fall under the corresponding headers.
     * There can be fewer elements in the row than headers.  Any data in columns outside
     * of the number of headers will not be added to the grid.
     *
     * @param rowData row data to add
     */
    public void addRow( Object[] rowData ) {
        int i = 0;

        for ( Iterator iter = columns.iterator(); iter.hasNext(); ) {
            Column each = (Column) iter.next();

            if ( i < rowData.length )
                each.addRow( rowData[ i ] );

            ++i;
        }
    }

    /**
     * Gives a string that represents the data formatted in columns.
     *
     * @return the formatted grid
     */
    public String format() {
        StringBuffer buffer = new StringBuffer();

        writeHeadersOn( buffer );
        writeSeparatorsOn( buffer );
        writeRowsOn( buffer );

        return buffer.toString();
    }

    /**
     * Removes all data from the grid, but preserves the headers.
     */
    public final void clear() {
        columns.clear();

        for ( int i = 0; i < headers.length; i++ )
            columns.add( new Column( headers[ i ] ) );
    }

    private void writeHeadersOn( StringBuffer buffer ) {
        for ( Iterator iter = columns.iterator(); iter.hasNext(); )
            ( (Column) iter.next() ).writeHeaderOn( buffer );

        buffer.append( LINE_SEPARATOR );
    }

    private void writeSeparatorsOn( StringBuffer buffer ) {
        for ( Iterator iter = columns.iterator(); iter.hasNext(); )
            ( (Column) iter.next() ).writeSeparatorOn( buffer );

        buffer.append( LINE_SEPARATOR );
    }

    private void writeRowsOn( StringBuffer buffer ) {
        int maxHeight =
            ( (Column) Collections.max( columns, Column.BY_HEIGHT ) ).height();

        for ( int i = 0; i < maxHeight; ++i )
            writeRowOn( buffer, i );
    }

    private void writeRowOn( StringBuffer buffer, int rowIndex ) {
        for ( Iterator iter = columns.iterator(); iter.hasNext(); )
            ( (Column) iter.next() ).writeCellOn( rowIndex, buffer );

        buffer.append( LINE_SEPARATOR );
    }
}
