/*******************************************************************************
 * Copyright (c) 2006 Sybase, Inc. and others.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Sybase, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.pagedesigner.css2.layout.table;

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

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.jst.jsf.common.ui.internal.logging.Logger;
import org.eclipse.jst.pagedesigner.PDPlugin;
import org.eclipse.jst.pagedesigner.css2.ICSSStyle;
import org.eclipse.jst.pagedesigner.css2.layout.CSSBlockFlowLayout;
import org.eclipse.jst.pagedesigner.css2.layout.CSSFigure;
import org.eclipse.jst.pagedesigner.css2.layout.ICSSPainter;
import org.eclipse.jst.pagedesigner.css2.property.ICSSPropertyID;
import org.eclipse.jst.pagedesigner.css2.style.ITagEditInfo;
import org.eclipse.swt.SWT;

/**
 * see also http://www.w3.org/TR/REC-CSS2/tables.html
 * 
 * @author mengbo
 * @version 1.5
 */
public class CSSTableLayout2 extends CSSBlockFlowLayout implements ICSSPainter {
	static Logger _log = PDPlugin.getLogger(CSSTableLayout2.class);

	int _hspacing;

	int _vspacing;

	int[] _columnWidths;

	int[] _rowHeights;

	Dimension _captionSize;

	// _tableInfo will be initialized in preLayout
	TableInfo _tableInfo;

	private int _internalTableWidth;

	private int _internalTableHeight;

	private int _rowx;

	private int _rowwidth;

	/**
	 * @param flowfigure
	 */
	public CSSTableLayout2(CSSFigure flowfigure) {
		super(flowfigure);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jst.pagedesigner.css2.layout.CSSBlockFlowLayout#preLayout()
	 */
	protected void preLayout() {
		// super.preLayout will setup the block box.
		super.preLayout();

		ICSSStyle style = this.getCSSStyle();

		_hspacing = _vspacing = 3; // default value

		if (style != null) {
			Object borderspacing = style
					.getStyleProperty(ICSSPropertyID.ATTR_BORDER_SPACING);
			if (borderspacing instanceof int[]) {
				int[] intvalues = (int[]) borderspacing;
				_hspacing = intvalues[0];
				_vspacing = intvalues[1];
			} else {
				ITagEditInfo info = (ITagEditInfo) style
						.getAdapter(ITagEditInfo.class);
				if (info != null && info.needTableDecorator()) {
					// default decorating value. to make things look more
					// separated.
					if (_hspacing < 5) {
						_hspacing = 5;
					}
					if (_vspacing < 5) {
						_vspacing = 5;
					}
				}
			}
		}

		// TODO: support caption
		_tableInfo = new TableInfo(getCSSFigure());

		// construct the table structure.
		_tableInfo.constructTable();

		// calculate the user specified width/height for table and cells.
		// contentWidth is the user specified content width. If <= 0 means no
		// user
		// specification.
		int contentWidth = this._blockBox.getContentWidth();
		int availableWidth = this._blockBox.getRecommendedContentWidth();
		int contentHeight = this._blockBox.getContentHeight();

		_tableInfo.calculateWidth(contentWidth, availableWidth);
		_tableInfo.calculateHeight(contentHeight);

		int columnCount = _tableInfo.getColumnCount();

		int columnMinWidths[] = new int[columnCount];
		int columnMaxWidths[] = new int[columnCount];

		// For each column, determine a maximum and minimum column width from
		// the cells that span only that column. The minimum is that required by
		// the cell with the largest minimum cell width (or the column 'width',
		// whichever is larger). The maximum is that required by the cell with
		// the
		// largest maximum cell width (or the column 'width', whichever is
		// larger).
		List cells = _tableInfo.getCells();
		for (int i = 0, size = cells.size(); i < size; i++) {
			TableCellInfo cellinfo = (TableCellInfo) cells.get(i);
			if (cellinfo.getColSpan() == 1) {
				int column = cellinfo.getColumnIndex();
				Dimension mincw = cellinfo.getMinCWDimension();
				Dimension maxcw = cellinfo.getMaxCWDimension();
				if (maxcw.width < mincw.width) {
					maxcw.width = mincw.width;
				}
				if (mincw.width > columnMinWidths[column]) {
					columnMinWidths[column] = mincw.width;
				}
				if (maxcw.width > columnMaxWidths[column]) {
					columnMaxWidths[column] = maxcw.width;
				}
			}
		}
		// For caption, determine a maximum and minimum width from it.
		int captionWidth = 0;
		if (_tableInfo._caption != null) {
			captionWidth = _tableInfo._caption.getDimension().width;
		}

		// For each cell that spans more than one column, increase the
		// minimum widths of the columns it spans so that together, they
		// are at least as wide as the cell. Do the same for the maximum
		// widths. If possible, widen all spanned columns by approximately
		// the same amount.
		for (int i = 0, size = cells.size(); i < size; i++) {
			TableCellInfo cellinfo = (TableCellInfo) cells.get(i);
			int colspan = cellinfo.getColSpan();
			if (colspan > 1) {
				int column = cellinfo.getColumnIndex();
				Dimension mincw = cellinfo.getMinCWDimension();
				Dimension maxcw = cellinfo.getMaxCWDimension();

				adjustWidth(column, colspan, mincw.width, columnMinWidths);
				adjustWidth(column, colspan, maxcw.width, columnMaxWidths);
			}
		}

		int sigmaMinWidth = 0;
		int sigmaMaxWidth = 0;
		for (int i = 0; i < columnMinWidths.length; i++) {
			sigmaMinWidth += columnMinWidths[i];
			if (columnMaxWidths[i] == Integer.MAX_VALUE) {
				sigmaMaxWidth = Integer.MAX_VALUE;
			} else if (sigmaMaxWidth != Integer.MAX_VALUE) {
				sigmaMaxWidth += columnMaxWidths[i];
				if (sigmaMaxWidth < 0) {
					sigmaMaxWidth = Integer.MAX_VALUE;
				}
			}
		}
		int spacingall = (columnMinWidths.length + 1) * _hspacing;
		sigmaMinWidth += spacingall;
		if (sigmaMaxWidth != Integer.MAX_VALUE) {
			sigmaMaxWidth += spacingall;
			if (sigmaMaxWidth < 0) {
				sigmaMaxWidth = Integer.MAX_VALUE;
			}
		}

		int tableWidth = _tableInfo.getTableWidth();
		if (tableWidth > 0) {
			// If the 'table' or 'inline-table' element's 'width' property has a
			// specified value (W) other than 'auto', the property's computed
			// value
			// is the greater of W and the minimum width required by all the
			// columns
			// plus cell spacing or borders (MIN). If W is greater than MIN, the
			// extra
			// width should be distributed over the columns.
			int maxMin = Math.max(captionWidth, sigmaMinWidth);
			if (maxMin >= tableWidth) {
				tableWidth = maxMin;
			}
			distribute(tableWidth - sigmaMinWidth, columnMinWidths,
					columnMaxWidths);
		} else {
			// If the 'table' or 'inline-table' element has 'width: auto', the
			// computed
			// table width is the greater of the table's containing block width
			// and MIN.
			// However, if the maximum width required by the columns plus cell
			// spacing or
			// borders (MAX) is less than that of the containing block, use MAX.
			// int availableWidth = this.getCurrentLine().getAvailableWidth();
			int maxMin = Math.max(captionWidth, sigmaMaxWidth);
			if (maxMin <= availableWidth) {
				// TODO: if _tableInfo.hasWidthPercentage, then we need take
				// that into consideration
				// to distribute the column width. Left to next version.
				tableWidth = maxMin;
				// columnMinWidths = columnMaxWidths;
			} else {
				tableWidth = availableWidth;
			}
			distribute(tableWidth - sigmaMinWidth, columnMinWidths,
					columnMaxWidths);
		}

		// now columnMinWidths contains width for each column
		_columnWidths = columnMinWidths;

		// ok, we have finished calculating column width.
		// next we need to find out row heights.
		_rowHeights = new int[_tableInfo.getRowCount()];

		// first find out those TR that has height settings and use them.
		List rows = _tableInfo.getRows();
		for (int i = 0, size = rows.size(); i < size && i < _rowHeights.length; i++) {
			TableRowInfo rowInfo = (TableRowInfo) rows.get(i);
			if (rowInfo.getSpecifiedRowHeight() > 0) {
				_rowHeights[i] = rowInfo.getSpecifiedRowHeight();
			}
		}

		// First the cells don't span multiple rows.
		cells = _tableInfo.getCells();
		for (int i = 0, size = cells.size(); i < size; i++) {
			TableCellInfo cellinfo = (TableCellInfo) cells.get(i);
			IFigure figure = cellinfo.getFigure();
			int rowspan = cellinfo.getRowSpan();
			if (rowspan == 1) {
				int cellWidth = getCellWidth(cellinfo, _columnWidths);
				Dimension d = figure.getPreferredSize(cellWidth, cellinfo
						.getHeight());
				if (d.height > _rowHeights[cellinfo.getRowIndex()]) {
					_rowHeights[cellinfo.getRowIndex()] = d.height;
				}
			}
		}

		// Next those cells span multiple rows.
		cells = _tableInfo.getCells();
		for (int i = 0, size = cells.size(); i < size; i++) {
			TableCellInfo cellinfo = (TableCellInfo) cells.get(i);
			IFigure figure = cellinfo.getFigure();
			int rowspan = cellinfo.getRowSpan();
			if (rowspan > 1) {
				int cellWidth = getCellWidth(cellinfo, _columnWidths);
				Dimension d = figure.getPreferredSize(cellWidth, cellinfo
						.getHeight());
				if (d.height > getCellHeight(cellinfo, _rowHeights)) {
					adjustHeight(cellinfo.getRowIndex(), rowspan, d.height,
							_rowHeights);
				}
			}
		}

		// Next we may need distribute height.
		int sigmaHeight = (_tableInfo.getRowCount() + 1) * _vspacing;
		for (int i = 0; i < _rowHeights.length; i++) {
			sigmaHeight += _rowHeights[i];
		}
		if (sigmaHeight < contentHeight) {
			distributeHeights(contentHeight - sigmaHeight, _rowHeights);
		}

		// now we have calculated the width and height of all cells.
		// FIXME: border?
		Insets insets = (style == null ? new Insets() : style.getBorderInsets()
				.getAdded(style.getPaddingInsets()));
		_internalTableWidth = (_tableInfo.getColumnCount() + 1) * _hspacing;
		for (int i = 0; i < _columnWidths.length; i++) {
			_internalTableWidth += _columnWidths[i];
		}
		int minWidth = getLengthValue(style, ICSSPropertyID.ATTR_MIN_WIDTH);
		_internalTableWidth = _internalTableWidth > minWidth ? _internalTableWidth
				: minWidth;

		_blockBox.setWidth(_internalTableWidth + insets.getWidth());
		_internalTableHeight = (_tableInfo.getRowCount() + 1) * _vspacing;
		for (int i = 0; i < _rowHeights.length; i++) {
			_internalTableHeight += _rowHeights[i];
		}
		int minHeight = getLengthValue(style, ICSSPropertyID.ATTR_MIN_HEIGHT);
		_internalTableHeight = _internalTableHeight > minHeight ? _internalTableHeight
				: minHeight;

		int captionHeight = 0;
		if (_tableInfo._caption != null) {
			_captionSize = _tableInfo._caption.getFigure().getPreferredSize(
					_internalTableWidth, SWT.DEFAULT);
			captionHeight = _captionSize.height;
		} else {
			_captionSize = null;
		}
		_internalTableHeight += captionHeight;

		_blockBox.setHeight(_internalTableHeight + insets.getHeight());

		_rowwidth = _internalTableWidth - 2 * _hspacing;
		_rowx = _hspacing; // XXX: table border width left?
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jst.pagedesigner.css2.layout.CSSBlockFlowLayout#endBlock()
	 */
	protected void endBlock() {
		_blockBox.setWidth(_internalTableWidth
				+ _blockBox.getBorderPaddingWidth());
		_blockBox.setHeight(_internalTableHeight
				+ _blockBox.getBorderPaddingHeight());
		super.endBlock();
	}

	//
	// /**
	// * when some of the column has percentage width, and sigmaMax smaller than
	// container,
	// * @param containerWidth
	// * @param columnMinWidths
	// * @param columnMaxWidths
	// * @return
	// */
	// private int distribute2(int containerWidth, int[] columnMinWidths, int[]
	// columnMaxWidths)
	// {
	//        
	// }
	//    
	/**
	 * Distribute the additional width to columnMinWidths, using max width as a
	 * possible reference on how to distribute.
	 * 
	 * @param toDistribute
	 * @param columnMinWidths
	 * @param columnMaxWidths
	 */
	private void distribute(int toDistribute, int[] columnMinWidths,
			int[] columnMaxWidths) {
		if (toDistribute <= 0)
			return;
		if (columnMinWidths.length == 0)
			return;

		int[] delta = new int[columnMinWidths.length];
		int sigmaDelta = 0;
		for (int i = 0; i < columnMinWidths.length && toDistribute > 0; i++) {
			if (_tableInfo._widthSpecified[i]) {
				delta[i] = 0;
			} else {
				delta[i] = columnMaxWidths[i] - columnMinWidths[i];
				if (delta[i] <= 0) {
					delta[i] = 0;
				}
				sigmaDelta += delta[i];
			}
		}
		if (sigmaDelta == 0) {
			// should not happen, but anyway, distribute all to the last column
			// columnMinWidths[columnMinWidths.length-1] += toDistribute;
			averageDeltaToCell(columnMinWidths, toDistribute);
		} else {
			int left = toDistribute;
			for (int i = 0; i < columnMinWidths.length - 1; i++) {
				if (delta[i] > 0) {
					int add = delta[i] * toDistribute / sigmaDelta;
					left -= add;
					columnMinWidths[i] += add;
				}
			}
			columnMinWidths[columnMinWidths.length - 1] += left;
		}
	}

	private void averageDeltaToCell(int[] columnMinWidths, int toDistribute) {

		if (toDistribute <= 0) {
			return;
		}
		ArrayList list = new ArrayList();
		for (int i = 0; i < columnMinWidths.length; i++) {
			if (!_tableInfo._widthSpecified[i]) {
				list.add(new Integer(i));
			}
		}
		if (list.size() == 0) {
			for (int i = 0; i < columnMinWidths.length; i++) {
				list.add(new Integer(i));
			}
		}
		int padding = toDistribute / list.size();
		int left = toDistribute % list.size();
		for (int i = 0, n = list.size(); i < n; i++) {
			columnMinWidths[((Integer) list.get(i)).intValue()] += padding;
		}
		if (left > 0) {
			for (int i = 0; i < left; i++) {
				columnMinWidths[((Integer) list.get(i)).intValue()] += 1;
			}
		}
	}

	/**
	 * @param i
	 * @param heights
	 */
	private void distributeHeights(int toDistribute, int[] heights) {
		if (heights.length == 0)
			return;
		int eachDelta = toDistribute / heights.length;
		for (int i = 0; i < heights.length - 1; i++) {
			heights[i] += eachDelta;
		}
		heights[heights.length - 1] += toDistribute - (heights.length - 1)
				* eachDelta;
	}

	/**
	 * @param cellinfo
	 * @param heights
	 * @return the cell height
	 */
	public int getCellHeight(TableCellInfo cellinfo, int[] heights) {
		int rowIndex = cellinfo.getRowIndex();
		int rowspan = cellinfo.getRowSpan();
		int h = 0;
		for (int i = 0; i < rowspan; i++) {
			h += heights[rowIndex + i];
		}
		h += (rowspan - 1) * _vspacing;
		return h;
	}

	/**
	 * @param cellinfo
	 * @param widths
	 * @return the cell width
	 */
	public int getCellWidth(TableCellInfo cellinfo, int[] widths) {
		int columnIndex = cellinfo.getColumnIndex();
		int colspan = cellinfo.getColSpan();
		int w = 0;
		for (int i = 0; i < colspan; i++) {
			w += widths[columnIndex + i];
		}
		w += (colspan - 1) * _hspacing;
		return w;
	}

	/**
	 * @param column
	 *            the start column
	 * @param colspan
	 *            number of columns
	 * @param width
	 *            desired width
	 * @param columnWidths
	 *            current columns widths. After the adjust, need make sure the
	 *            columnWidths to be bigger than desired width
	 */
	private void adjustWidth(int column, int colspan, int width,
			int[] columnWidths) {
		adjustSpan(column, colspan, width, columnWidths, _hspacing);
	}

	/**
	 * @see #adjustWidth(int, int, int, int[])
	 */
	private void adjustHeight(int rowIndex, int rowspan, int height,
			int[] heights) {
		adjustSpan(rowIndex, rowspan, height, heights, _vspacing);
	}

	static private void adjustSpan(int column, int colspan, int width,
			int[] columnWidths, int spacing) {
		int spanwidth = 0;
		for (int i = 0; i < colspan; i++) {
			spanwidth += columnWidths[column + i];
		}
		// XXX: vspacing here?
		spanwidth += (colspan - 1) * spacing;

		if (spanwidth >= width) {
			return;
		}
        int delta = width - spanwidth;
        int deltaeach = delta / colspan;
        for (int i = 0; i < colspan - 1; i++) {
        	columnWidths[column + i] += deltaeach;
        }
        columnWidths[column + colspan - 1] += (delta - (colspan - 1)
        		* deltaeach);
	}

	/**
	 * @return the row heights
	 */
	public int[] getRowHeights() {
		return _rowHeights;
	}

	/**
	 * @return the column widths
	 */
	public int[] getColumnWidths() {
		return _columnWidths;
	}

	/**
	 * @return the vertical spacing value
	 */
	public int getVSpacing() {
		return _vspacing;
	}

	/**
	 * @return the horizontal spacing value
	 */
	public int getHSpacing() {
		return _hspacing;
	}

	/**
	 * @param figure
	 * @return the table row info for the figure
	 */
	public TableRowInfo getRowInfo(CSSFigure figure) {
		return _tableInfo.findRowInfo(figure);
	}

	/**
	 * @return the table caption info
	 */
	public TableCaptionInfo getCaptionInfo() {
		return _tableInfo._caption;
	}

	/**
	 * @param figure
	 * @return the table row group info for the figure
	 */
	public TableRowGroupInfo getGroupInfo(CSSFigure figure) {
		return _tableInfo.findGroupInfo(figure);
	}

	/**
	 * @return the row's x
	 */
	public int getRowX() {
		return _rowx;
	}

	/**
	 * @return the row's width
	 */
	public int getRowWidth() {
		return _rowwidth;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jst.pagedesigner.css2.layout.CSSBlockFlowLayout#shouldExpand()
	 */
	public boolean shouldExpand() {
		return false;
	}

	/**
	 * @return the rendered dimensions of the table caption
	 */
	public Dimension getCaptionSize() {
		return _captionSize;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jst.pagedesigner.css2.layout.ICSSPainter#paintFigure(org.eclipse.draw2d.Graphics)
	 */
	public void paintFigure(Graphics g) {
		ICSSStyle style = this.getCSSStyle();
		if (style != null) {
			ITagEditInfo info = (ITagEditInfo) style
					.getAdapter(ITagEditInfo.class);
			if (info != null && info.needTableDecorator()) {
				List cells = _tableInfo.getCells();
				for (int i = 0, size = cells.size(); i < size; i++) {
					TableCellInfo cellInfo = (TableCellInfo) cells.get(i);
					IFigure cellfigure = cellInfo.getFigure();
					Rectangle rect = cellfigure.getBounds().getCopy();
					rect = rect.expand(1, 1);
					g.setLineStyle(Graphics.LINE_SOLID);
					g.setLineWidth(1);
					g.setForegroundColor(ColorConstants.lightGray);
					g.drawRectangle(rect);
				}
			}
		}
	}

}
