/*
 * 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.
 */

/* $Id$ */

package org.apache.fop.layoutmgr.table;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.fop.area.Area;
import org.apache.fop.area.Block;
import org.apache.fop.datatypes.LengthBase;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.flow.Marker;
import org.apache.fop.fo.flow.Markers;
import org.apache.fop.fo.flow.RetrieveTableMarker;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableColumn;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.layoutmgr.BlockLevelEventProducer;
import org.apache.fop.layoutmgr.BreakElement;
import org.apache.fop.layoutmgr.BreakOpportunity;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthGlue;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.LeafPosition;
import org.apache.fop.layoutmgr.ListElement;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.PositionIterator;
import org.apache.fop.layoutmgr.SpacedBorderedPaddedBlockLayoutManager;
import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.traits.SpaceVal;
import org.apache.fop.util.BreakUtil;

/**
 * LayoutManager for a table FO.
 * A table consists of columns, table header, table footer and multiple
 * table bodies.
 * The header, footer and body add the areas created from the table cells.
 * The table then creates areas for the columns, bodies and rows
 * the render background.
 */
public class TableLayoutManager extends SpacedBorderedPaddedBlockLayoutManager
        implements BreakOpportunity {

    /**
     * logging instance
     */
    private static Log log = LogFactory.getLog(TableLayoutManager.class);

    private TableContentLayoutManager contentLM;
    private ColumnSetup columns;

    private Block curBlockArea;

    private double tableUnit;
    private boolean autoLayout = true;

    private int halfBorderSeparationBPD;
    private int halfBorderSeparationIPD;

    /** See {@link TableLayoutManager#registerColumnBackgroundArea(TableColumn, Block, int)}. */
    private List columnBackgroundAreas;

    private Position auxiliaryPosition;

    // this holds a possible list of TCLMs that needed to have their addAreas() repeated
    private List<TableCellLayoutManager> savedTCLMs;
    private boolean areAllTCLMsSaved;

    private Markers tableMarkers;
    private Markers tableFragmentMarkers;

    private boolean hasRetrieveTableMarker;

    private boolean repeatedHeader;

    private List<List<KnuthElement>> headerFootnotes = Collections.emptyList();

    private List<List<KnuthElement>> footerFootnotes = Collections.emptyList();

    /**
     * Temporary holder of column background informations for a table-cell's area.
     *
     * @see TableLayoutManager#registerColumnBackgroundArea(TableColumn, Block, int)
     */
    private static final class ColumnBackgroundInfo {
        private TableColumn column;
        private Block backgroundArea;
        private int xShift;

        private ColumnBackgroundInfo(TableColumn column, Block backgroundArea, int xShift) {
            this.column = column;
            this.backgroundArea = backgroundArea;
            this.xShift = xShift;
        }
    }

    /**
     * Create a new table layout manager.
     * @param node the table FO
     */
    public TableLayoutManager(Table node) {
        super(node);
        this.columns = new ColumnSetup(node);
    }


    @Override
    protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
        return getTable().getCommonBorderPaddingBackground();
    }


    /** @return the table FO */
    public Table getTable() {
        return (Table)this.fobj;
    }

    /**
     * @return the column setup for this table.
     */
    public ColumnSetup getColumns() {
        return this.columns;
    }

    /** {@inheritDoc} */
    public void initialize() {
        foSpaceBefore = new SpaceVal(
                getTable().getCommonMarginBlock().spaceBefore, this).getSpace();
        foSpaceAfter = new SpaceVal(
                getTable().getCommonMarginBlock().spaceAfter, this).getSpace();
        startIndent = getTable().getCommonMarginBlock().startIndent.getValue(this);
        endIndent = getTable().getCommonMarginBlock().endIndent.getValue(this);

        if (getTable().isSeparateBorderModel()) {
            this.halfBorderSeparationBPD = getTable().getBorderSeparation().getBPD().getLength()
                    .getValue(this) / 2;
            this.halfBorderSeparationIPD = getTable().getBorderSeparation().getIPD().getLength()
                    .getValue(this) / 2;
        } else {
            this.halfBorderSeparationBPD = 0;
            this.halfBorderSeparationIPD = 0;
        }

        if (!getTable().isAutoLayout()
                && getTable().getInlineProgressionDimension().getOptimum(this).getEnum()
                    != EN_AUTO) {
            autoLayout = false;
        }
    }

    private void resetSpaces() {
        this.discardBorderBefore = false;
        this.discardBorderAfter = false;
        this.discardPaddingBefore = false;
        this.discardPaddingAfter = false;
        this.effSpaceBefore = null;
        this.effSpaceAfter = null;
    }

    /**
     * @return half the value of border-separation.block-progression-dimension, or 0 if
     * border-collapse="collapse".
     */
    public int getHalfBorderSeparationBPD() {
        return halfBorderSeparationBPD;
    }

    /**
     * @return half the value of border-separation.inline-progression-dimension, or 0 if
     * border-collapse="collapse".
     */
    public int getHalfBorderSeparationIPD() {
        return halfBorderSeparationIPD;
    }

    /** {@inheritDoc} */
    public List getNextKnuthElements(LayoutContext context, int alignment) {

        List returnList = new LinkedList();

        /*
         * Compute the IPD and adjust it if necessary (overconstrained)
         */
        referenceIPD = context.getRefIPD();
        if (getTable().getInlineProgressionDimension().getOptimum(this).getEnum() != EN_AUTO) {
            int contentIPD = getTable().getInlineProgressionDimension().getOptimum(this)
                    .getLength().getValue(this);
            updateContentAreaIPDwithOverconstrainedAdjust(contentIPD);
        } else {
            if (!getTable().isAutoLayout()) {
                BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get(
                        getTable().getUserAgent().getEventBroadcaster());
                eventProducer.tableFixedAutoWidthNotSupported(this, getTable().getLocator());
            }
            updateContentAreaIPDwithOverconstrainedAdjust();
        }
        int sumOfColumns = columns.getSumOfColumnWidths(this);
        if (!autoLayout && sumOfColumns > getContentAreaIPD()) {
            log.debug(FONode.decorateWithContextInfo(
                    "The sum of all column widths is larger than the specified table width.",
                    getTable()));
            updateContentAreaIPDwithOverconstrainedAdjust(sumOfColumns);
        }
        int availableIPD = referenceIPD - getIPIndents();
        if (getContentAreaIPD() > availableIPD) {
            BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get(
                    getTable().getUserAgent().getEventBroadcaster());
            eventProducer.objectTooWide(this, getTable().getName(),
                    getContentAreaIPD(), context.getRefIPD(),
                    getTable().getLocator());
        }

        /* initialize unit to determine computed values
         * for proportional-column-width()
         */
        if (tableUnit == 0.0) {
            this.tableUnit = columns.computeTableUnit(this);
        }

        if (!firstVisibleMarkServed) {
            addKnuthElementsForSpaceBefore(returnList, alignment);
        }

        if (getTable().isSeparateBorderModel()) {
            addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed);
            firstVisibleMarkServed = true;
            // Border and padding to be repeated at each break
            // This must be done only in the separate-border model, as in collapsing
            // tables have no padding and borders are determined at the cell level
            addPendingMarks(context);
        }


        // Elements for the table-header/footer/body
        List contentKnuthElements;
        contentLM = new TableContentLayoutManager(this);
        LayoutContext childLC = LayoutContext.newInstance();
        /*
        childLC.setStackLimit(
              MinOptMax.subtract(context.getStackLimit(),
                                 stackSize));*/
        childLC.setRefIPD(context.getRefIPD());
        childLC.copyPendingMarksFrom(context);

        contentKnuthElements = contentLM.getNextKnuthElements(childLC, alignment);
        //Set index values on elements coming from the content LM
        for (Object contentKnuthElement : contentKnuthElements) {
            ListElement el = (ListElement) contentKnuthElement;
            notifyPos(el.getPosition());
        }
        log.debug(contentKnuthElements);
        wrapPositionElements(contentKnuthElements, returnList);

        context.updateKeepWithPreviousPending(getKeepWithPrevious());
        context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending());

        context.updateKeepWithNextPending(getKeepWithNext());
        context.updateKeepWithNextPending(childLC.getKeepWithNextPending());

        if (getTable().isSeparateBorderModel()) {
            addKnuthElementsForBorderPaddingAfter(returnList, true);
        }
        addKnuthElementsForSpaceAfter(returnList, alignment);

        if (!context.suppressBreakBefore()) {
            //addKnuthElementsForBreakBefore(returnList, context);
            int breakBefore = BreakUtil.compareBreakClasses(getTable().getBreakBefore(),
                    childLC.getBreakBefore());
            if (breakBefore != Constants.EN_AUTO) {
                returnList.add(0, new BreakElement(new LeafPosition(getParent(), 0), 0,
                        -KnuthElement.INFINITE, breakBefore, context));
            }
        }

        //addKnuthElementsForBreakAfter(returnList, context);
        int breakAfter = BreakUtil.compareBreakClasses(getTable().getBreakAfter(),
                childLC.getBreakAfter());
        if (breakAfter != Constants.EN_AUTO) {
            returnList.add(new BreakElement(new LeafPosition(getParent(), 0),
                    0, -KnuthElement.INFINITE, breakAfter, context));
        }

        setFinished(true);
        resetSpaces();
        return returnList;
    }

    /** {@inheritDoc} */
    public Position getAuxiliaryPosition() {
        /*
         * Redefined to return a LeafPosition instead of a NonLeafPosition. The
         * SpaceResolver.SpaceHandlingBreakPosition constructors unwraps all
         * NonLeafPositions, which can lead to a NPE when a break in a table occurs at a
         * page with different ipd.
         */
        if (auxiliaryPosition == null) {
            auxiliaryPosition = new LeafPosition(this, 0);
        }
        return auxiliaryPosition;
    }

    /**
     * Registers the given area, that will be used to render the part of column background
     * covered by a table-cell. If percentages are used to place the background image, the
     * final bpd of the (fraction of) table that will be rendered on the current page must
     * be known. The traits can't then be set when the areas for the cell are created
     * since at that moment this bpd is yet unknown. So they will instead be set in
     * TableLM's {@link #addAreas(PositionIterator, LayoutContext)} method.
     *
     * @param column the table-column element from which the cell gets background
     * informations
     * @param backgroundArea the block of the cell's dimensions that will hold the column
     * background
     * @param xShift additional amount by which the image must be shifted to be correctly
     * placed (to counterbalance the cell's start border)
     */
    void registerColumnBackgroundArea(TableColumn column, Block backgroundArea, int xShift) {
        addBackgroundArea(backgroundArea);
        if (columnBackgroundAreas == null) {
            columnBackgroundAreas = new ArrayList();
        }
        columnBackgroundAreas.add(new ColumnBackgroundInfo(column, backgroundArea, xShift));
    }

    /**
     * The table area is a reference area that contains areas for
     * columns, bodies, rows and the contents are in cells.
     *
     * @param parentIter the position iterator
     * @param layoutContext the layout context for adding areas
     */
    public void addAreas(PositionIterator parentIter,
                         LayoutContext layoutContext) {
        getParentArea(null);
        addId();

        // add space before, in order to implement display-align = "center" or "after"
        if (layoutContext.getSpaceBefore() != 0) {
            addBlockSpacing(0.0, MinOptMax.getInstance(layoutContext.getSpaceBefore()));
        }

        int startXOffset = getTable().getCommonMarginBlock().startIndent.getValue(this);

        // add column, body then row areas

        // BPD of the table, i.e., height of its content; table's borders and paddings not counted
        int tableHeight = 0;
        //Body childLM;
        LayoutContext lc = LayoutContext.offspringOf(layoutContext);


        lc.setRefIPD(getContentAreaIPD());
        contentLM.setStartXOffset(startXOffset);
        contentLM.addAreas(parentIter, lc);
        tableHeight += contentLM.getUsedBPD();

        curBlockArea.setBPD(tableHeight);

        if (columnBackgroundAreas != null) {
            for (Object columnBackgroundArea : columnBackgroundAreas) {
                ColumnBackgroundInfo b = (ColumnBackgroundInfo) columnBackgroundArea;
                TraitSetter.addBackground(b.backgroundArea,
                        b.column.getCommonBorderPaddingBackground(), this,
                        b.xShift, -b.backgroundArea.getYOffset(),
                        b.column.getColumnWidth().getValue(this), tableHeight);
            }
            columnBackgroundAreas.clear();
        }

        if (getTable().isSeparateBorderModel()) {
            TraitSetter.addBorders(curBlockArea,
                    getTable().getCommonBorderPaddingBackground(),
                    discardBorderBefore, discardBorderAfter, false, false, this);
            TraitSetter.addPadding(curBlockArea,
                    getTable().getCommonBorderPaddingBackground(),
                    discardPaddingBefore, discardPaddingAfter, false, false, this);
        }
        TraitSetter.addBackground(curBlockArea,
                getTable().getCommonBorderPaddingBackground(),
                this);
        TraitSetter.addMargins(curBlockArea,
                getTable().getCommonBorderPaddingBackground(),
                startIndent, endIndent,
                this);
        TraitSetter.addBreaks(curBlockArea,
                getTable().getBreakBefore(), getTable().getBreakAfter());
        TraitSetter.addSpaceBeforeAfter(curBlockArea, layoutContext.getSpaceAdjust(),
                effSpaceBefore, effSpaceAfter);

        flush();

        resetSpaces();
        curBlockArea = null;

        notifyEndOfLayout();
    }

    /**
     * Return an Area which can contain the passed childArea. The childArea
     * may not yet have any content, but it has essential traits set.
     * In general, if the LayoutManager already has an Area it simply returns
     * it. Otherwise, it makes a new Area of the appropriate class.
     * It gets a parent area for its area by calling its parent LM.
     * Finally, based on the dimensions of the parent area, it initializes
     * its own area. This includes setting the content IPD and the maximum
     * BPD.
     *
     * @param childArea the child area
     * @return the parent area of the child
     */
    public Area getParentArea(Area childArea) {
        if (curBlockArea == null) {
            curBlockArea = new Block();
            curBlockArea.setChangeBarList(getChangeBarList());

            // Set up dimensions
            // Must get dimensions from parent area
            /*Area parentArea =*/ parentLayoutManager.getParentArea(curBlockArea);

            TraitSetter.setProducerID(curBlockArea, getTable().getId());

            curBlockArea.setIPD(getContentAreaIPD());

            setCurrentArea(curBlockArea);
        }
        return curBlockArea;
    }

    /**
     * Add the child area to this layout manager.
     *
     * @param childArea the child area to add
     */
    public void addChildArea(Area childArea) {
        if (curBlockArea != null) {
            curBlockArea.addBlock((Block) childArea);
        }
    }

    /**
     * Adds the given area to this layout manager's area, without updating the used bpd.
     *
     * @param background an area
     */
    void addBackgroundArea(Block background) {
        curBlockArea.addChildArea(background);
    }

    /** {@inheritDoc} */
    public int negotiateBPDAdjustment(int adj, KnuthElement lastElement) {
        // TODO Auto-generated method stub
        return 0;
    }

    /** {@inheritDoc} */
    public void discardSpace(KnuthGlue spaceGlue) {
        // TODO Auto-generated method stub

    }

    /** {@inheritDoc} */
    public KeepProperty getKeepTogetherProperty() {
        return getTable().getKeepTogether();
    }

    /** {@inheritDoc} */
    public KeepProperty getKeepWithPreviousProperty() {
        return getTable().getKeepWithPrevious();
    }

    /** {@inheritDoc} */
    public KeepProperty getKeepWithNextProperty() {
        return getTable().getKeepWithNext();
    }

    // --------- Property Resolution related functions --------- //

    /**
     * {@inheritDoc}
     */
    public int getBaseLength(int lengthBase, FObj fobj) {
        // Special handler for TableColumn width specifications
        if (fobj instanceof TableColumn && fobj.getParent() == getFObj()) {
            switch (lengthBase) {
            case LengthBase.CONTAINING_BLOCK_WIDTH:
                return getContentAreaIPD();
            case LengthBase.TABLE_UNITS:
                return (int) this.tableUnit;
            default:
                log.error("Unknown base type for LengthBase.");
                return 0;
            }
        } else {
            switch (lengthBase) {
            case LengthBase.TABLE_UNITS:
                return (int) this.tableUnit;
            default:
                return super.getBaseLength(lengthBase, fobj);
            }
        }
    }

    /** {@inheritDoc} */
    public void reset() {
        super.reset();
        curBlockArea = null;
        tableUnit = 0.0;
    }

    /**
     * Saves a TableCellLayoutManager for later use.
     *
     * @param tclm a TableCellLayoutManager that has a RetrieveTableMarker
     */
    protected void saveTableHeaderTableCellLayoutManagers(TableCellLayoutManager tclm) {
        if (savedTCLMs == null) {
            savedTCLMs = new ArrayList<TableCellLayoutManager>();
        }
        if (!areAllTCLMsSaved) {
            savedTCLMs.add(tclm);
        }
    }

    /**
     * Calls addAreas() for each of the saved TableCellLayoutManagers.
     */
    protected void repeatAddAreasForSavedTableHeaderTableCellLayoutManagers() {
        if (savedTCLMs == null) {
            return;
        }
        // if we get to this stage then we are at the footer of the table fragment; this means that no more
        // different TCLM need to be saved (we already have all); we flag the list as being complete then
        areAllTCLMsSaved = true;
        for (TableCellLayoutManager tclm : savedTCLMs) {
            if (this.repeatedHeader) {
                tclm.setHasRepeatedHeader(true);
            }
            tclm.repeatAddAreas();
        }
    }

    /**
     * Resolves a RetrieveTableMarker by finding a qualifying Marker to which it is bound to.
     * @param rtm the RetrieveTableMarker to be resolved
     * @return a bound RetrieveTableMarker instance or null if no qualifying Marker found
     */
    public RetrieveTableMarker resolveRetrieveTableMarker(RetrieveTableMarker rtm) {
        String name = rtm.getRetrieveClassName();
        int originalPosition = rtm.getPosition();
        boolean changedPosition = false;

        Marker mark = null;
        // try the primary retrieve scope area, which is the same as table-fragment
        mark = (tableFragmentMarkers == null) ? null : tableFragmentMarkers.resolve(rtm);
        if (mark == null && rtm.getBoundary() != Constants.EN_TABLE_FRAGMENT) {
            rtm.changePositionTo(Constants.EN_LAST_ENDING);
            changedPosition = true;
            // try the page scope area
            mark = getCurrentPV().resolveMarker(rtm);
            if (mark == null && rtm.getBoundary() != Constants.EN_PAGE) {
                // try the table scope area
                mark = (tableMarkers == null) ? null : tableMarkers.resolve(rtm);
            }
        }
        if (changedPosition) {
            // so that the next time it is called looks unchanged
            rtm.changePositionTo(originalPosition);
        }
        if (mark == null) {
            log.debug("found no marker with name: " + name);
            return null;
        } else {
            rtm.bindMarker(mark);
            return rtm;
        }
    }

    /**
     * Register the markers for this table.
     *
     * @param marks the map of markers to add
     * @param starting if the area being added is starting or ending
     * @param isfirst if the area being added has is-first trait
     * @param islast if the area being added has is-last trait
     */
    public void registerMarkers(Map<String, Marker> marks, boolean starting, boolean isfirst,
            boolean islast) {
        if (tableMarkers == null) {
            tableMarkers = new Markers();
        }
        tableMarkers.register(marks, starting, isfirst, islast);
        if (tableFragmentMarkers == null) {
            tableFragmentMarkers = new Markers();
        }
        tableFragmentMarkers.register(marks, starting, isfirst, islast);
    }

    /**
     * Clears the list of markers in the current table fragment. Should be called just before starting a new
     * header (that belongs to the next table fragment).
     */
    protected void clearTableFragmentMarkers() {
        tableFragmentMarkers = null;
    }

    public void flagAsHavingRetrieveTableMarker() {
        hasRetrieveTableMarker = true;
    }

    protected void possiblyRegisterMarkersForTables(Map<String, Marker> markers, boolean isStarting,
            boolean isFirst, boolean isLast) {
        // note: if we allow table-footer after a table-body this check should not be made and the markers
        // should be registered regardless because the retrieval may be done only in the footer
        if (hasRetrieveTableMarker) {
            registerMarkers(markers, isStarting, isFirst, isLast);
        }
        super.possiblyRegisterMarkersForTables(markers, isStarting, isFirst, isLast);
    }

    void setHeaderFootnotes(List<List<KnuthElement>> footnotes) {
        this.headerFootnotes = footnotes;
    }

    List<List<KnuthElement>> getHeaderFootnotes() {
        return headerFootnotes;
    }

    void setFooterFootnotes(List<List<KnuthElement>> footnotes) {
        this.footerFootnotes = footnotes;
    }

    public void setRepeateHeader(boolean repeateHeader) {
        this.repeatedHeader = repeateHeader;
    }

    List<List<KnuthElement>> getFooterFootnotes() {
        return footerFootnotes;
    }

}
