/*
 *  ====================================================================
 *    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.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.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.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";
    /* package */ static final String DRAWINGML_URI = "http://schemas.openxmlformats.org/drawingml/2006/main";

    private CTTable _table;
    private List<XSLFTableRow> _rows;

    /*package*/ XSLFTable(CTGraphicalObjectFrame shape, XSLFSheet sheet){
        super(shape, sheet);

        CTGraphicalObjectData god = shape.getGraphic().getGraphicData();
        XmlCursor xc = god.newCursor();
        if (!xc.toChild(DRAWINGML_URI, "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 the full ooxml-schemas jar but may happen with the abridged poi-ooxml-schemas
        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 - use POIXMLTypeLoader.setClassLoader() to set the loader, " +
                "e.g. with CTTable.class.getClassLoader()"
            ;
            throw new IllegalStateException(errStr);
        }
        _table = (CTTable)xo;
        xc.dispose();

        _rows = new ArrayList<XSLFTableRow>(_table.sizeOfTrArray());
        for(CTTableRow row : _table.getTrArray()) {
            _rows.add(new XSLFTableRow(row, this));
        }
        updateRowColIndexes();
    }

    @Override
    public XSLFTableCell getCell(int row, int col) {
        List<XSLFTableRow> rows = getRows();
        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(
                _table.getTblGrid().getGridColArray(idx).getW());
    }

    @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(_table.getTrArray(row).getH());
    }
    
    @Override
    public void setRowHeight(int row, double height) {
        _table.getTrArray(row).setH(Units.toEMU(height));
    }
    
    public Iterator<XSLFTableRow> iterator(){
        return _rows.iterator();
    }

    public List<XSLFTableRow> getRows(){
        return Collections.unmodifiableList(_rows);
    }

    public XSLFTableRow addRow(){
        CTTableRow tr = _table.addNewTr();
        XSLFTableRow row = new XSLFTableRow(tr, this);
        // default height is 20 points
        row.setHeight(20.0);    
        _rows.add(row);
        updateRowColIndexes();
        return row;
    }

    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 + 1);
        nvGr.addNewCNvGraphicFramePr().addNewGraphicFrameLocks().setNoGrp(true);
        nvGr.addNewNvPr();

        frame.addNewXfrm();
        CTGraphicalObjectData gr = frame.addNewGraphic().addNewGraphicData();
        XmlCursor grCur = gr.newCursor();
        grCur.toNextToken();
        grCur.beginElement(new QName(DRAWINGML_URI, "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
     */
    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(true);
	    			}
    			}
    			if(mergeColumnRequired) {
    				if(colPos == firstCol) {
    					cell.setGridSpan(colSpan);
    				} else {
    					cell.setHMerge(true);
    				}
    			}
    		}
    	}
    }
    
    /**
     * 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++;
        }
    }

    /* package */ 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 newY = tblAnc.getY();

        // #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++) {
            double newX = tblAnc.getX();
            for (int col=0; col<cols; col++) {
                Rectangle2D bounds = new Rectangle2D.Double(newX, newY, colWidths[col], rowHeights[row]);
                XSLFTableCell tc = getCell(row, col);
                if (tc != null) {
                    tc.setAnchor(bounds);
                    newX += colWidths[col]+DrawTableShape.borderSize;
                }
            }
            newY += 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);
            }
        }
        
    }
}
