/*
 *  ====================================================================
 *    Licensed to the Apache Software Foundation (ASF) under one or more
 *    contributor license agreements.  See the NOTICE file distributed with
 *    this work for additional information regarding copyright ownership.
 *    The ASF licenses this file to You under the Apache License, Version 2.0
 *    (the "License"); you may not use this file except in compliance with
 *    the License.  You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 * ====================================================================
 */

package org.apache.poi.xslf.usermodel;

import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import javax.xml.namespace.QName;

import org.apache.poi.ooxml.util.POIXMLUnits;
import org.apache.poi.sl.draw.DrawFactory;
import org.apache.poi.sl.draw.DrawTableShape;
import org.apache.poi.sl.draw.DrawTextShape;
import org.apache.poi.sl.usermodel.TableShape;
import org.apache.poi.util.Internal;
import org.apache.poi.util.Units;
import org.apache.poi.xddf.usermodel.text.XDDFTextBody;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.impl.values.XmlAnyTypeImpl;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTable;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCol;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableRow;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrameNonVisual;

/**
 * Represents a table in a .pptx presentation
 */
public class XSLFTable extends XSLFGraphicFrame implements Iterable<XSLFTableRow>,
    TableShape<XSLFShape,XSLFTextParagraph> {
    /* package */ static final String TABLE_URI = "http://schemas.openxmlformats.org/drawingml/2006/table";

    private final CTTable _table;
    private final List<XSLFTableRow> _rows;

    /*package*/ XSLFTable(CTGraphicalObjectFrame shape, XSLFSheet sheet){
        super(shape, sheet);

        CTGraphicalObjectData god = shape.getGraphic().getGraphicData();
        XmlCursor xc = god.newCursor();
        try {
            if (!xc.toChild(XSLFRelation.NS_DRAWINGML, "tbl")) {
                throw new IllegalStateException("a:tbl element was not found in\n " + god);
            }

            XmlObject xo = xc.getObject();
            // Pesky XmlBeans bug - see Bugzilla #49934
            // it never happens when using poi-ooxml-full jar but may happen with the abridged poi-ooxml-lite jar
            if (xo instanceof XmlAnyTypeImpl){
                String errStr =
                    "Schemas (*.xsb) for CTTable can't be loaded - usually this happens when OSGI " +
                    "loading is used and the thread context classloader has no reference to " +
                    "the xmlbeans classes"
                ;
                throw new IllegalStateException(errStr);
            }
            _table = (CTTable)xo;
        } finally {
            xc.dispose();
        }

        _rows = new ArrayList<>(_table.sizeOfTrArray());
        for(CTTableRow row : _table.getTrList()) {
            _rows.add(new XSLFTableRow(row, this));
        }
        updateRowColIndexes();
    }

    @Override
    public XSLFTableCell getCell(int row, int col) {
        if (row < 0 || _rows.size() <= row) {
            return null;
        }
        XSLFTableRow r = _rows.get(row);
        if (r == null) {
            // empty row
            return null;
        }
        List<XSLFTableCell> cells = r.getCells();
        if (col < 0 || cells.size() <= col) {
            return null;
        }
        // cell can be potentially empty ...
        return cells.get(col);
    }

    @Internal
    public CTTable getCTTable(){
        return _table;
    }

    @Override
    public int getNumberOfColumns() {
        return _table.getTblGrid().sizeOfGridColArray();
    }

    @Override
    public int getNumberOfRows() {
        return _table.sizeOfTrArray();
    }

    @Override
    public double getColumnWidth(int idx){
        return Units.toPoints(POIXMLUnits.parseLength(
                _table.getTblGrid().getGridColArray(idx).xgetW()));
    }

    @Override
    public void setColumnWidth(int idx, double width) {
        _table.getTblGrid().getGridColArray(idx).setW(Units.toEMU(width));
    }

    @Override
    public double getRowHeight(int row) {
        return Units.toPoints(POIXMLUnits.parseLength(_table.getTrArray(row).xgetH()));
    }

    @Override
    public void setRowHeight(int row, double height) {
        _table.getTrArray(row).setH(Units.toEMU(height));
    }

    @Override
    public Iterator<XSLFTableRow> iterator(){
        return _rows.iterator();
    }

    public List<XSLFTableRow> getRows(){
        return Collections.unmodifiableList(_rows);
    }

    public XSLFTableRow addRow(){
        CTTableRow tr = _table.addNewTr();
        XSLFTableRow row = initializeRow(tr);
        _rows.add(row);
        updateRowColIndexes();
        return row;
    }

    private XSLFTableRow initializeRow(CTTableRow tr) {
        XSLFTableRow row = new XSLFTableRow(tr, this);
        // default height is 20 points
        row.setHeight(20.0);
        return row;
    }

    /**
     * Insert a new row at the given index.
     * @param rowIdx the row index.
     * @since POI 5.0.0
     */
    public XSLFTableRow insertRow(int rowIdx) {
        if (getNumberOfRows() < rowIdx) {
            throw new IndexOutOfBoundsException("Cannot insert row at " + rowIdx + "; table has only " + getNumberOfRows() + "rows.");
        }
        CTTableRow tr = _table.insertNewTr(rowIdx);
        XSLFTableRow row = initializeRow(tr);
        for (int i = 0;  i < getNumberOfColumns(); i++) {
            row.addCell();
        }
        _rows.add(rowIdx, row);
        return row;
    }

    /**
     * Remove the row on the given index
     * @param rowIdx the row index
     */
    public void removeRow(int rowIdx) {
        if (getNumberOfRows() < rowIdx) {
            throw new IndexOutOfBoundsException("Cannot remove row at " + rowIdx + "; table has only " + getNumberOfRows() + "rows.");
        }
        _table.removeTr(rowIdx);
        _rows.remove(rowIdx);
        updateRowColIndexes();
    }

    /**
     * Add a new column at the end of the table.
     * @since POI 4.1.2
     */
    public void addColumn() {
        long width = POIXMLUnits.parseLength(_table.getTblGrid().getGridColArray(getNumberOfColumns() - 1).xgetW());
        CTTableCol col = _table.getTblGrid().addNewGridCol();
        col.setW(width);
        for (XSLFTableRow row : _rows) {
            XSLFTableCell cell = row.addCell();
            new XDDFTextBody(cell, cell.getTextBody(true)).initialize();
        }
    }

    /**
     * Insert a new column at the given index.
     * @param colIdx the column index.
     * @since POI 4.1.2
     */
    public void insertColumn(int colIdx) {
        if (getNumberOfColumns() < colIdx) {
            throw new IndexOutOfBoundsException("Cannot insert column at " + colIdx + "; table has only " + getNumberOfColumns() + "columns.");
        }
        long width = POIXMLUnits.parseLength(_table.getTblGrid().getGridColArray(colIdx).xgetW());
        CTTableCol col = _table.getTblGrid().insertNewGridCol(colIdx);
        col.setW(width);
        for (XSLFTableRow row : _rows) {
            XSLFTableCell cell = row.insertCell(colIdx);
            new XDDFTextBody(cell, cell.getTextBody(true)).initialize();
        }
    }

    /**
     * Remove the column at the given index.
     * @param colIdx the column index.
     * @since POI 4.1.2
     */
    public void removeColumn(int colIdx) {
        if (getNumberOfColumns() < colIdx) {
            throw new IndexOutOfBoundsException("Cannot remove column at " + colIdx + "; table has only " + getNumberOfColumns() + "columns.");
        }
        _table.getTblGrid().removeGridCol(colIdx);
        for (XSLFTableRow row : _rows) {
            row.removeCell(colIdx);
        }
    }

    static CTGraphicalObjectFrame prototype(int shapeId){
        CTGraphicalObjectFrame frame = CTGraphicalObjectFrame.Factory.newInstance();
        CTGraphicalObjectFrameNonVisual nvGr = frame.addNewNvGraphicFramePr();

        CTNonVisualDrawingProps cnv = nvGr.addNewCNvPr();
        cnv.setName("Table " + shapeId);
        cnv.setId(shapeId);
        nvGr.addNewCNvGraphicFramePr().addNewGraphicFrameLocks().setNoGrp(true);
        nvGr.addNewNvPr();

        frame.addNewXfrm();
        CTGraphicalObjectData gr = frame.addNewGraphic().addNewGraphicData();
        XmlCursor grCur = gr.newCursor();
        grCur.toNextToken();
        grCur.beginElement(new QName(XSLFRelation.NS_DRAWINGML, "tbl"));

        CTTable tbl = CTTable.Factory.newInstance();
        tbl.addNewTblPr();
        tbl.addNewTblGrid();
        XmlCursor tblCur = tbl.newCursor();

        tblCur.moveXmlContents(grCur);
        tblCur.dispose();
        grCur.dispose();
        gr.setUri(TABLE_URI);
        return frame;
    }

    /**
     * Merge cells of a table
     */
    @SuppressWarnings("unused")
    public void mergeCells(int firstRow, int lastRow, int firstCol, int lastCol) {

    	if(firstRow > lastRow) {
    		throw new IllegalArgumentException(
    			"Cannot merge, first row > last row : "
    			+ firstRow + " > " + lastRow
    		);
    	}

    	if(firstCol > lastCol) {
    		throw new IllegalArgumentException(
    			"Cannot merge, first column > last column : "
    			+ firstCol + " > " + lastCol
    		);
    	}

    	int rowSpan = (lastRow - firstRow) + 1;
    	boolean mergeRowRequired = rowSpan > 1;

    	int colSpan = (lastCol - firstCol) + 1;
    	boolean mergeColumnRequired = colSpan > 1;

    	for(int i = firstRow; i <= lastRow; i++) {

    		XSLFTableRow row = _rows.get(i);

    		for(int colPos = firstCol; colPos <= lastCol; colPos++) {

    			XSLFTableCell cell = row.getCells().get(colPos);

    			if(mergeRowRequired) {
	    			if(i == firstRow) {
	    				cell.setRowSpan(rowSpan);
	    			} else {
	    				cell.setVMerge();
	    			}
    			}
    			if(mergeColumnRequired) {
    				if(colPos == firstCol) {
    					cell.setGridSpan(colSpan);
    				} else {
    					cell.setHMerge();
    				}
    			}
    		}
    	}
    }

    /**
     * Get assigned TableStyle
     *
     * @return the assigned TableStyle
     *
     * @since POI 3.15-beta2
     */
    protected XSLFTableStyle getTableStyle() {
        CTTable tab = getCTTable();
        // TODO: support inline table style
        if (!tab.isSetTblPr() || !tab.getTblPr().isSetTableStyleId()) {
            return null;
        }

        String styleId = tab.getTblPr().getTableStyleId();
        XSLFTableStyles styles = getSheet().getSlideShow().getTableStyles();
        for (XSLFTableStyle style : styles.getStyles()) {
            if (style.getStyleId().equals(styleId)) {
                return style;
            }
        }
        return null;
    }

    /* package */ void updateRowColIndexes() {
        int rowIdx = 0;
        for (XSLFTableRow xr : this) {
            int colIdx = 0;
            for (XSLFTableCell tc : xr) {
                tc.setRowColIndex(rowIdx, colIdx);
                colIdx++;
            }
            rowIdx++;
        }
    }

    /**
     * Calculates the bounding boxes of all cells and updates the dimension of the table
     */
    public void updateCellAnchor() {
        int rows = getNumberOfRows();
        int cols = getNumberOfColumns();

        double[] colWidths = new double[cols];
        double[] rowHeights = new double[rows];

        for (int row=0; row<rows; row++) {
            rowHeights[row] = getRowHeight(row);
        }
        for (int col=0; col<cols; col++) {
            colWidths[col] = getColumnWidth(col);
        }

        Rectangle2D tblAnc = getAnchor();
        DrawFactory df = DrawFactory.getInstance(null);

        double nextY = tblAnc.getY();
        double nextX = tblAnc.getX();

        // #1 pass - determine row heights, the height values might be too low or 0 ...
        for (int row=0; row<rows; row++) {
            double maxHeight = 0;
            for (int col=0; col<cols; col++) {
                XSLFTableCell tc = getCell(row, col);
                if (tc == null || tc.getGridSpan() != 1 || tc.getRowSpan() != 1) {
                    continue;
                }
                // need to set the anchor before height calculation
                tc.setAnchor(new Rectangle2D.Double(0,0,colWidths[col],0));
                DrawTextShape dts = df.getDrawable(tc);
                maxHeight = Math.max(maxHeight, dts.getTextHeight());
            }
            rowHeights[row] = Math.max(rowHeights[row],maxHeight);
        }

        // #2 pass - init properties
        for (int row=0; row<rows; row++) {
            nextX = tblAnc.getX();
            for (int col=0; col<cols; col++) {
                Rectangle2D bounds = new Rectangle2D.Double(nextX, nextY, colWidths[col], rowHeights[row]);
                XSLFTableCell tc = getCell(row, col);
                if (tc != null) {
                    tc.setAnchor(bounds);
                    nextX += colWidths[col]+DrawTableShape.borderSize;
                }
            }
            nextY += rowHeights[row]+DrawTableShape.borderSize;
        }

        // #3 pass - update merge info
        for (int row=0; row<rows; row++) {
            for (int col=0; col<cols; col++) {
                XSLFTableCell tc = getCell(row, col);
                if (tc == null) {
                    continue;
                }
                Rectangle2D mergedBounds = tc.getAnchor();
                for (int col2=col+1; col2<col+tc.getGridSpan(); col2++) {
                    assert(col2 < cols);
                    XSLFTableCell tc2 = getCell(row, col2);
                    assert(tc2.getGridSpan() == 1 && tc2.getRowSpan() == 1);
                    mergedBounds.add(tc2.getAnchor());
                }
                for (int row2=row+1; row2<row+tc.getRowSpan(); row2++) {
                    assert(row2 < rows);
                    XSLFTableCell tc2 = getCell(row2, col);
                    assert(tc2.getGridSpan() == 1 && tc2.getRowSpan() == 1);
                    mergedBounds.add(tc2.getAnchor());
                }
                tc.setAnchor(mergedBounds);
            }
        }

        setAnchor(new Rectangle2D.Double(tblAnc.getX(),tblAnc.getY(),
                nextX-tblAnc.getX(),
                nextY-tblAnc.getY()));
    }
}
