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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.apps.FOPException;
import org.apache.fop.datatypes.Numeric;

import org.apache.fop.area.AreaTreeHandler;
import org.apache.fop.area.AreaTreeModel;
import org.apache.fop.area.Block;
import org.apache.fop.area.Footnote;
import org.apache.fop.area.PageViewport;
import org.apache.fop.area.LineArea;
import org.apache.fop.area.Resolvable;

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.RetrieveMarker;

import org.apache.fop.fo.pagination.Flow;
import org.apache.fop.fo.pagination.PageSequence;
import org.apache.fop.fo.pagination.Region;
import org.apache.fop.fo.pagination.RegionBody;
import org.apache.fop.fo.pagination.SideRegion;
import org.apache.fop.fo.pagination.SimplePageMaster;
import org.apache.fop.fo.pagination.StaticContent;
import org.apache.fop.layoutmgr.PageBreakingAlgorithm.PageBreakingLayoutListener;
import org.apache.fop.layoutmgr.inline.ContentLayoutManager;

import org.apache.fop.traits.MinOptMax;

import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

/**
 * LayoutManager for a PageSequence.  This class is instantiated by
 * area.AreaTreeHandler for each fo:page-sequence found in the
 * input document.
 */
public class PageSequenceLayoutManager extends AbstractLayoutManager {

    private static Log log = LogFactory.getLog(PageSequenceLayoutManager.class);

    /** 
     * AreaTreeHandler which activates the PSLM and controls
     * the rendering of its pages.
     */
    private AreaTreeHandler areaTreeHandler;

    /** 
     * fo:page-sequence formatting object being
     * processed by this class
     */
    private PageSequence pageSeq;

    private PageProvider pageProvider;
    
    /** 
     * Current page with page-viewport-area being filled by
     * the PSLM.
     */
    private Page curPage = null;

    /**
     * The FlowLayoutManager object, which processes
     * the single fo:flow of the fo:page-sequence
     */
    private FlowLayoutManager childFLM = null;

    private int startPageNum = 0;
    private int currentPageNum = 0;

    private Block separatorArea = null;
    
    /**
     * Constructor
     *
     * @param ath the area tree handler object
     * @param pseq fo:page-sequence to process
     */
    public PageSequenceLayoutManager(AreaTreeHandler ath, PageSequence pseq) {
        super(pseq);
        this.areaTreeHandler = ath;
        this.pageSeq = pseq;
        this.pageProvider = new PageProvider(this.pageSeq);
    }

    /**
     * @see org.apache.fop.layoutmgr.LayoutManager
     * @return the LayoutManagerMaker object
     */
    public LayoutManagerMaker getLayoutManagerMaker() {
        return areaTreeHandler.getLayoutManagerMaker();
    }

    /** @return the PageProvider applicable to this page-sequence. */
    public PageProvider getPageProvider() {
        return this.pageProvider;
    }
    
    /**
     * Activate the layout of this page sequence.
     * PageViewports corresponding to each page generated by this 
     * page sequence will be created and sent to the AreaTreeModel
     * for rendering.
     */
    public void activateLayout() {
        startPageNum = pageSeq.getStartingPageNumber();
        currentPageNum = startPageNum - 1;

        LineArea title = null;

        if (pageSeq.getTitleFO() != null) {
            try {
                ContentLayoutManager clm = getLayoutManagerMaker().
                    makeContentLayoutManager(this, pageSeq.getTitleFO());
                title = (LineArea) clm.getParentArea(null);
            } catch (IllegalStateException e) {
                // empty title; do nothing
            }
        }

        areaTreeHandler.getAreaTreeModel().startPageSequence(title);
        log.debug("Starting layout");

        curPage = makeNewPage(false, false);

        
        Flow mainFlow = pageSeq.getMainFlow();
        childFLM = getLayoutManagerMaker().
            makeFlowLayoutManager(this, mainFlow);

        PageBreaker breaker = new PageBreaker(this);
        int flowBPD = (int)getCurrentPV().getBodyRegion().getRemainingBPD();
        breaker.doLayout(flowBPD);

        finishPage();
    }
        
    /**
     * Finished the page-sequence and notifies everyone about it.
     */
    public void finishPageSequence() {
        if (!pageSeq.getId().equals("")) {
            areaTreeHandler.signalIDProcessed(pageSeq.getId());
        }

        pageSeq.getRoot().notifyPageSequenceFinished(currentPageNum,
                (currentPageNum - startPageNum) + 1);
        areaTreeHandler.notifyPageSequenceFinished(pageSeq,
                (currentPageNum - startPageNum) + 1);
        pageSeq.releasePageSequence();
        log.debug("Ending layout");
    }


    private class PageBreaker extends AbstractBreaker {
        
        private PageSequenceLayoutManager pslm;
        private boolean firstPart = true;
        private boolean pageBreakHandled;
        private boolean needColumnBalancing;
        
        private StaticContentLayoutManager footnoteSeparatorLM = null;

        public PageBreaker(PageSequenceLayoutManager pslm) {
            this.pslm = pslm;
        }
        
        /** @see org.apache.fop.layoutmgr.AbstractBreaker */
        protected void updateLayoutContext(LayoutContext context) {
            int flowIPD = getCurrentPV().getCurrentSpan().getColumnWidth();
            context.setRefIPD(flowIPD);
        }
        
        /** @see org.apache.fop.layoutmgr.AbstractBreaker#getTopLevelLM() */
        protected LayoutManager getTopLevelLM() {
            return pslm;
        }
        
        /** @see org.apache.fop.layoutmgr.AbstractBreaker#getPageProvider() */
        protected PageSequenceLayoutManager.PageProvider getPageProvider() {
            return pageProvider;
        }
        
        /**
         * @see org.apache.fop.layoutmgr.AbstractBreaker#getLayoutListener()
         */
        protected PageBreakingLayoutListener getLayoutListener() {
            return new PageBreakingLayoutListener() {

                public void notifyOverflow(int part, FObj obj) {
                    Page p = pageProvider.getPage(
                                false, part, PageProvider.RELTO_CURRENT_ELEMENT_LIST);
                    RegionBody body = (RegionBody)p.getSimplePageMaster().getRegion(
                            Region.FO_REGION_BODY);
                    String err = FONode.decorateWithContextInfo(
                            "Content of the region-body on page " 
                            + p.getPageViewport().getPageNumberString() 
                            + " overflows the available area in block-progression dimension.", 
                            obj);
                    if (body.getOverflow() == Constants.EN_ERROR_IF_OVERFLOW) {
                        throw new RuntimeException(err);
                    } else {
                        PageSequenceLayoutManager.log.warn(err);
                    }
                }
                
            };
        }

        /** @see org.apache.fop.layoutmgr.AbstractBreaker */
        protected int handleSpanChange(LayoutContext childLC, int nextSequenceStartsOn) {
            needColumnBalancing = false;
            if (childLC.getNextSpan() != Constants.NOT_SET) {
                //Next block list will have a different span.
                nextSequenceStartsOn = childLC.getNextSpan();
                needColumnBalancing = (childLC.getNextSpan() == Constants.EN_ALL);
            }
            if (needColumnBalancing) {
                AbstractBreaker.log.debug(
                        "Column balancing necessary for the next element list!!!");
            }
            return nextSequenceStartsOn;
        }

        /** @see org.apache.fop.layoutmgr.AbstractBreaker */
        protected int getNextBlockList(LayoutContext childLC, 
                int nextSequenceStartsOn, 
                List blockLists) {
            if (!firstPart) {
                // if this is the first page that will be created by
                // the current BlockSequence, it could have a break
                // condition that must be satisfied;
                // otherwise, we may simply need a new page
                handleBreakTrait(nextSequenceStartsOn);
            }
            firstPart = false;
            pageBreakHandled = true;
            pageProvider.setStartOfNextElementList(currentPageNum, 
                    getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
            return super.getNextBlockList(childLC, nextSequenceStartsOn, blockLists);
        }
        
        /** @see org.apache.fop.layoutmgr.AbstractBreaker */
        protected LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
            LinkedList contentList = null;
            
            while (!childFLM.isFinished() && contentList == null) {
                contentList = childFLM.getNextKnuthElements(context, alignment);
            }

            // scan contentList, searching for footnotes
            boolean bFootnotesPresent = false;
            if (contentList != null) {
                ListIterator contentListIterator = contentList.listIterator();
                while (contentListIterator.hasNext()) {
                    ListElement element = (ListElement) contentListIterator.next();
                    if (element instanceof KnuthBlockBox
                        && ((KnuthBlockBox) element).hasAnchors()) {
                        // element represents a line with footnote citations
                        bFootnotesPresent = true;
                        LayoutContext footnoteContext = new LayoutContext(context);
                        footnoteContext.setStackLimit(context.getStackLimit());
                        footnoteContext.setRefIPD(getCurrentPV()
                                .getRegionReference(Constants.FO_REGION_BODY).getIPD());
                        LinkedList footnoteBodyLMs = ((KnuthBlockBox) element).getFootnoteBodyLMs();
                        ListIterator footnoteBodyIterator = footnoteBodyLMs.listIterator();
                        // store the lists of elements representing the footnote bodies
                        // in the box representing the line containing their references
                        while (footnoteBodyIterator.hasNext()) {
                            FootnoteBodyLayoutManager fblm 
                                = (FootnoteBodyLayoutManager) footnoteBodyIterator.next();
                            fblm.setParent(childFLM);
                            fblm.initialize();
                            ((KnuthBlockBox) element).addElementList(
                                    fblm.getNextKnuthElements(footnoteContext, alignment));
                        }
                    }
                }
            }

            // handle the footnote separator
            StaticContent footnoteSeparator;
            if (bFootnotesPresent
                    && (footnoteSeparator = pageSeq.getStaticContent(
                                            "xsl-footnote-separator")) != null) {
                // the footnote separator can contain page-dependent content such as
                // page numbers or retrieve markers, so its areas cannot simply be 
                // obtained now and repeated in each page;
                // we need to know in advance the separator bpd: the actual separator
                // could be different from page to page, but its bpd would likely be
                // always the same

                // create a Block area that will contain the separator areas
                separatorArea = new Block();
                separatorArea.setIPD(pslm.getCurrentPV()
                            .getRegionReference(Constants.FO_REGION_BODY).getIPD());
                // create a StaticContentLM for the footnote separator
                footnoteSeparatorLM = (StaticContentLayoutManager)
                    getLayoutManagerMaker().makeStaticContentLayoutManager(
                    pslm, footnoteSeparator, separatorArea);
                footnoteSeparatorLM.doLayout();

                footnoteSeparatorLength = new MinOptMax(separatorArea.getBPD());
            }
            return contentList;
        }
        
        protected int getCurrentDisplayAlign() {
            return curPage.getSimplePageMaster().getRegion(
                    Constants.FO_REGION_BODY).getDisplayAlign();
        }
        
        protected boolean hasMoreContent() {
            return !childFLM.isFinished();
        }
        
        protected void addAreas(PositionIterator posIter, LayoutContext context) {
            if (footnoteSeparatorLM != null) {
                StaticContent footnoteSeparator = pageSeq.getStaticContent(
                        "xsl-footnote-separator");
                // create a Block area that will contain the separator areas
                separatorArea = new Block();
                separatorArea.setIPD(
                        getCurrentPV().getRegionReference(Constants.FO_REGION_BODY).getIPD());
                // create a StaticContentLM for the footnote separator
                footnoteSeparatorLM = (StaticContentLayoutManager)
                    getLayoutManagerMaker().makeStaticContentLayoutManager(
                    pslm, footnoteSeparator, separatorArea);
                footnoteSeparatorLM.doLayout();
            }

            childFLM.addAreas(posIter, context);    
        }
        
        protected void doPhase3(PageBreakingAlgorithm alg, int partCount, 
                BlockSequence originalList, BlockSequence effectiveList) {
            if (needColumnBalancing) {
                doPhase3WithColumnBalancing(alg, partCount, originalList, effectiveList);
            } else {
                if (!hasMoreContent() && pageSeq.hasPagePositionLast()) {
                    //last part is reached and we have a "last page" condition
                    doPhase3WithLastPage(alg, partCount, originalList, effectiveList);
                } else {
                    //Directly add areas after finding the breaks
                    addAreas(alg, partCount, originalList, effectiveList);
                }
            }
        }

        private void doPhase3WithLastPage(PageBreakingAlgorithm alg, int partCount, 
                BlockSequence originalList, BlockSequence effectiveList) {
            int newStartPos;
            int restartPoint = pageProvider.getStartingPartIndexForLastPage(partCount);
            if (restartPoint > 0) {
                //Add definitive areas before last page
                addAreas(alg, restartPoint, originalList, effectiveList);
                //Get page break from which we restart
                PageBreakPosition pbp = (PageBreakPosition)
                        alg.getPageBreaks().get(restartPoint - 1);
                newStartPos = pbp.getLeafPos();
                //Handle page break right here to avoid any side-effects
                if (newStartPos > 0) {
                    handleBreakTrait(EN_PAGE);
                }
            } else {
                newStartPos = 0;
            }
            AbstractBreaker.log.debug("Last page handling now!!!");
            AbstractBreaker.log.debug("===================================================");
            AbstractBreaker.log.debug("Restarting at " + restartPoint 
                    + ", new start position: " + newStartPos);

            pageBreakHandled = true;
            //Update so the available BPD is reported correctly
            pageProvider.setStartOfNextElementList(currentPageNum, 
                    getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
            pageProvider.setLastPageIndex(currentPageNum);

            //Restart last page
            PageBreakingAlgorithm algRestart = new PageBreakingAlgorithm(
                    getTopLevelLM(),
                    getPageProvider(), getLayoutListener(),
                    alg.getAlignment(), alg.getAlignmentLast(), 
                    footnoteSeparatorLength,
                    isPartOverflowRecoveryActivated(), false, false);
            //alg.setConstantLineWidth(flowBPD);
            int iOptPageCount = algRestart.findBreakingPoints(effectiveList,
                        newStartPos,
                        1, true, BreakingAlgorithm.ALL_BREAKS);
            AbstractBreaker.log.debug("restart: iOptPageCount= " + iOptPageCount
                    + " pageBreaks.size()= " + algRestart.getPageBreaks().size());
            boolean replaceLastPage 
                    = iOptPageCount <= getCurrentPV().getBodyRegion().getColumnCount(); 
            if (replaceLastPage) {

                //Replace last page
                pslm.curPage = pageProvider.getPage(false, currentPageNum);
                //Make sure we only add the areas we haven't added already
                effectiveList.ignoreAtStart = newStartPos;
                addAreas(algRestart, iOptPageCount, originalList, effectiveList);
            } else {
                effectiveList.ignoreAtStart = newStartPos;
                addAreas(alg, restartPoint, partCount - restartPoint, originalList, effectiveList);
                //Add blank last page
                pageProvider.setLastPageIndex(currentPageNum + 1);
                pslm.curPage = makeNewPage(true, true);
            }
            AbstractBreaker.log.debug("===================================================");
        }

        private void doPhase3WithColumnBalancing(PageBreakingAlgorithm alg, int partCount, 
                BlockSequence originalList, BlockSequence effectiveList) {
            AbstractBreaker.log.debug("Column balancing now!!!");
            AbstractBreaker.log.debug("===================================================");
            int newStartPos;
            int restartPoint = pageProvider.getStartingPartIndexForLastPage(partCount);
            if (restartPoint > 0) {
                //Add definitive areas
                addAreas(alg, restartPoint, originalList, effectiveList);
                //Get page break from which we restart
                PageBreakPosition pbp = (PageBreakPosition)
                        alg.getPageBreaks().get(restartPoint - 1);
                newStartPos = pbp.getLeafPos();
                //Handle page break right here to avoid any side-effects
                if (newStartPos > 0) {
                    handleBreakTrait(EN_PAGE);
                }
            } else {
                newStartPos = 0;
            }
            AbstractBreaker.log.debug("Restarting at " + restartPoint 
                    + ", new start position: " + newStartPos);

            pageBreakHandled = true;
            //Update so the available BPD is reported correctly
            pageProvider.setStartOfNextElementList(currentPageNum, 
                    getCurrentPV().getCurrentSpan().getCurrentFlowIndex());

            //Restart last page
            PageBreakingAlgorithm algRestart = new BalancingColumnBreakingAlgorithm(
                    getTopLevelLM(),
                    getPageProvider(), getLayoutListener(),
                    alignment, Constants.EN_START, footnoteSeparatorLength,
                    isPartOverflowRecoveryActivated(),
                    getCurrentPV().getBodyRegion().getColumnCount());
            //alg.setConstantLineWidth(flowBPD);
            int iOptPageCount = algRestart.findBreakingPoints(effectiveList,
                        newStartPos,
                        1, true, BreakingAlgorithm.ALL_BREAKS);
            AbstractBreaker.log.debug("restart: iOptPageCount= " + iOptPageCount
                    + " pageBreaks.size()= " + algRestart.getPageBreaks().size());
            if (iOptPageCount > getCurrentPV().getBodyRegion().getColumnCount()) {
                AbstractBreaker.log.warn(
                        "Breaking algorithm produced more columns than are available.");
                /* reenable when everything works
                throw new IllegalStateException(
                        "Breaking algorithm must not produce more columns than available.");
                */
            }
            //Make sure we only add the areas we haven't added already
            effectiveList.ignoreAtStart = newStartPos;
            addAreas(algRestart, iOptPageCount, originalList, effectiveList);
            AbstractBreaker.log.debug("===================================================");
        }
        
        protected void startPart(BlockSequence list, int breakClass) {
            AbstractBreaker.log.debug("startPart() breakClass=" + breakClass);
            if (curPage == null) {
                throw new IllegalStateException("curPage must not be null");
            }
            if (!pageBreakHandled) {
                
                //firstPart is necessary because we need the first page before we start the 
                //algorithm so we have a BPD and IPD. This may subject to change later when we
                //start handling more complex cases.
                if (!firstPart) {
                    // if this is the first page that will be created by
                    // the current BlockSequence, it could have a break
                    // condition that must be satisfied;
                    // otherwise, we may simply need a new page
                    handleBreakTrait(breakClass);
                }
                pageProvider.setStartOfNextElementList(currentPageNum, 
                        getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
            }
            pageBreakHandled = false;
            // add static areas and resolve any new id areas
            // finish page and add to area tree
            firstPart = false;
        }
        
        /** @see org.apache.fop.layoutmgr.AbstractBreaker#handleEmptyContent() */
        protected void handleEmptyContent() {
            getCurrentPV().getPage().fakeNonEmpty();
        }
        
        protected void finishPart(PageBreakingAlgorithm alg, PageBreakPosition pbp) {
            // add footnote areas
            if (pbp.footnoteFirstListIndex < pbp.footnoteLastListIndex
                || pbp.footnoteFirstElementIndex <= pbp.footnoteLastElementIndex) {
                // call addAreas() for each FootnoteBodyLM
                for (int i = pbp.footnoteFirstListIndex; i <= pbp.footnoteLastListIndex; i++) {
                    LinkedList elementList = alg.getFootnoteList(i);
                    int firstIndex = (i == pbp.footnoteFirstListIndex 
                            ? pbp.footnoteFirstElementIndex : 0);
                    int lastIndex = (i == pbp.footnoteLastListIndex 
                            ? pbp.footnoteLastElementIndex : elementList.size() - 1);

                    SpaceResolver.performConditionalsNotification(elementList, 
                            firstIndex, lastIndex, -1);
                    LayoutContext childLC = new LayoutContext(0);
                    AreaAdditionUtil.addAreas(null, 
                            new KnuthPossPosIter(elementList, firstIndex, lastIndex + 1), 
                            childLC);
                }
                // set the offset from the top margin
                Footnote parentArea = (Footnote) getCurrentPV().getBodyRegion().getFootnote();
                int topOffset = (int) getCurrentPV().getBodyRegion().getBPD() - parentArea.getBPD();
                if (separatorArea != null) {
                    topOffset -= separatorArea.getBPD();
                }
                parentArea.setTop(topOffset);
                parentArea.setSeparator(separatorArea);
            }
            getCurrentPV().getCurrentSpan().notifyFlowsFinished();
        }
        
        protected LayoutManager getCurrentChildLM() {
            return childFLM;
        }
        
        /** @see org.apache.fop.layoutmgr.AbstractBreaker#observeElementList(java.util.List) */
        protected void observeElementList(List elementList) {
            ElementListObserver.observe(elementList, "breaker", 
                    ((PageSequence)pslm.getFObj()).getId());
        }
        
    }
    
    /**
     * Provides access to the current page.
     * @return the current Page
     */
    public Page getCurrentPage() {
        return curPage;
    }

    /**
     * Provides access to the current page viewport.
     * @return the current PageViewport
     *//*
    public PageViewport getCurrentPageViewport() {
        return curPage.getPageViewport();
    }*/

    /**
     * Provides access to this object
     * @return this PageSequenceLayoutManager instance
     */
    public PageSequenceLayoutManager getPSLM() {
        return this;
    }
    
    /**
     * This returns the first PageViewport that contains an id trait
     * matching the idref argument, or null if no such PV exists.
     *
     * @param idref the idref trait needing to be resolved 
     * @return the first PageViewport that contains the ID trait
     */
    public PageViewport getFirstPVWithID(String idref) {
        List list = areaTreeHandler.getPageViewportsContainingID(idref);
        if (list != null && list.size() > 0) {
            return (PageViewport) list.get(0);
        }
        return null;
    }

    /**
     * This returns the last PageViewport that contains an id trait
     * matching the idref argument, or null if no such PV exists.
     *
     * @param idref the idref trait needing to be resolved 
     * @return the last PageViewport that contains the ID trait
     */
    public PageViewport getLastPVWithID(String idref) {
        List list = areaTreeHandler.getPageViewportsContainingID(idref);
        if (list != null && list.size() > 0) {
            return (PageViewport) list.get(list.size() - 1);
        }
        return null;
    }
    
    /**
     * Add an ID reference to the current page.
     * When adding areas the area adds its ID reference.
     * For the page layout manager it adds the id reference
     * with the current page to the area tree.
     *
     * @param id the ID reference to add
     */
    public void addIDToPage(String id) {
        if (id != null && id.length() > 0) {
            areaTreeHandler.associateIDWithPageViewport(id, curPage.getPageViewport());
        }
    }
    
    /**
     * Add an id reference of the layout manager in the AreaTreeHandler,
     * if the id hasn't been resolved yet
     * @param id the id to track
     * @return a boolean indicating if the id has already been resolved
     * TODO Maybe give this a better name
     */
    public boolean associateLayoutManagerID(String id) {
        if (log.isDebugEnabled()) {
            log.debug("associateLayoutManagerID(" + id + ")");
        }
        if (!areaTreeHandler.alreadyResolvedID(id)) {
            areaTreeHandler.signalPendingID(id);
            return false;
        } else {
            return true;
        }
    }
    
    /**
     * Notify the areaTreeHandler that the LayoutManagers containing
     * idrefs have finished creating areas
     * @param id the id for which layout has finished
     */
    public void notifyEndOfLayout(String id) {
        areaTreeHandler.signalIDProcessed(id);
    }
    
    /**
     * Identify an unresolved area (one needing an idref to be 
     * resolved, e.g. the internal-destination of an fo:basic-link)
     * for both the AreaTreeHandler and PageViewport object.
     * 
     * The AreaTreeHandler keeps a document-wide list of idref's
     * and the PV's needing them to be resolved.  It uses this to  
     * send notifications to the PV's when an id has been resolved.
     * 
     * The PageViewport keeps lists of id's needing resolving, along
     * with the child areas (page-number-citation, basic-link, etc.)
     * of the PV needing their resolution.
     *
     * @param id the ID reference to add
     * @param res the resolvable object that needs resolving
     */
    public void addUnresolvedArea(String id, Resolvable res) {
        curPage.getPageViewport().addUnresolvedIDRef(id, res);
        areaTreeHandler.addUnresolvedIDRef(id, curPage.getPageViewport());
    }

    /**
     * Bind the RetrieveMarker to the corresponding Marker subtree.
     * If the boundary is page then it will only check the
     * current page. For page-sequence and document it will
     * lookup preceding pages from the area tree and try to find
     * a marker.
     * If we retrieve a marker from a preceding page,
     * then the containing page does not have a qualifying area,
     * and all qualifying areas have ended.
     * Therefore we use last-ending-within-page (Constants.EN_LEWP)
     * as the position. 
     *
     * @param rm the RetrieveMarker instance whose properties are to
     * used to find the matching Marker.
     * @return a bound RetrieveMarker instance, or null if no Marker
     * could be found.
     */
    public RetrieveMarker resolveRetrieveMarker(RetrieveMarker rm) {
        AreaTreeModel areaTreeModel = areaTreeHandler.getAreaTreeModel();
        String name = rm.getRetrieveClassName();
        int pos = rm.getRetrievePosition();
        int boundary = rm.getRetrieveBoundary();               
        
        // get marker from the current markers on area tree
        Marker mark = (Marker)getCurrentPV().getMarker(name, pos);
        if (mark == null && boundary != EN_PAGE) {
            // go back over pages until mark found
            // if document boundary then keep going
            boolean doc = boundary == EN_DOCUMENT;
            int seq = areaTreeModel.getPageSequenceCount();
            int page = areaTreeModel.getPageCount(seq) - 1;
            while (page < 0 && doc && seq > 1) {
                seq--;
                page = areaTreeModel.getPageCount(seq) - 1;
            }
            while (page >= 0) {
                PageViewport pv = areaTreeModel.getPage(seq, page);
                mark = (Marker)pv.getMarker(name, Constants.EN_LEWP);
                if (mark != null) {
                    break;
                }
                page--;
                if (page < 0 && doc && seq > 1) {
                    seq--;
                    page = areaTreeModel.getPageCount(seq) - 1;
                }
            }
        }

        if (mark == null) {
            log.debug("found no marker with name: " + name);
            return null;
        } else {
            rm.bindMarker(mark);
            return rm;
        }
    }

    private Page makeNewPage(boolean bIsBlank, boolean bIsLast) {
        if (curPage != null) {
            finishPage();
        }

        currentPageNum++;

        curPage = pageProvider.getPage(bIsBlank,
                currentPageNum, PageProvider.RELTO_PAGE_SEQUENCE);

        if (log.isDebugEnabled()) {
            log.debug("[" + curPage.getPageViewport().getPageNumberString() 
                    + (bIsBlank ? "*" : "") + "]");
        }
        
        addIDToPage(pageSeq.getId());
        return curPage;
    }

    private void layoutSideRegion(int regionID) {
        SideRegion reg = (SideRegion)curPage.getSimplePageMaster().getRegion(regionID);
        if (reg == null) {
            return;
        }
        StaticContent sc = pageSeq.getStaticContent(reg.getRegionName());
        if (sc == null) {
            return;
        }

        StaticContentLayoutManager lm = (StaticContentLayoutManager)
            getLayoutManagerMaker().makeStaticContentLayoutManager(
                    this, sc, reg);
        lm.doLayout();
    }

    private void finishPage() {
        curPage.getPageViewport().dumpMarkers();
        // Layout side regions
        layoutSideRegion(FO_REGION_BEFORE); 
        layoutSideRegion(FO_REGION_AFTER);
        layoutSideRegion(FO_REGION_START);
        layoutSideRegion(FO_REGION_END);
        
        // Try to resolve any unresolved IDs for the current page.
        // 
        areaTreeHandler.tryIDResolution(curPage.getPageViewport());
        // Queue for ID resolution and rendering
        areaTreeHandler.getAreaTreeModel().addPage(curPage.getPageViewport());
        if (log.isDebugEnabled()) {
            log.debug("page finished: " + curPage.getPageViewport().getPageNumberString() 
                    + ", current num: " + currentPageNum);
        }
        curPage = null;
    }
    
    /**
     * Depending on the kind of break condition, move to next column
     * or page. May need to make an empty page if next page would
     * not have the desired "handedness".
     * @param breakVal - value of break-before or break-after trait.
     */
    private void handleBreakTrait(int breakVal) {
        if (breakVal == Constants.EN_ALL) {
            //break due to span change in multi-column layout
            curPage.getPageViewport().createSpan(true);
            return;
        } else if (breakVal == Constants.EN_NONE) {
            curPage.getPageViewport().createSpan(false);
            return;
        } else if (breakVal == Constants.EN_COLUMN || breakVal <= 0) {
            PageViewport pv = curPage.getPageViewport();
            
            //Check if previous page was spanned
            boolean forceNewPageWithSpan = false;
            RegionBody rb = (RegionBody)curPage.getSimplePageMaster().getRegion(
                    Constants.FO_REGION_BODY);
            if (breakVal < 0 
                    && rb.getColumnCount() > 1 
                    && pv.getCurrentSpan().getColumnCount() == 1) {
                forceNewPageWithSpan = true;
            }
            
            if (forceNewPageWithSpan) {
                curPage = makeNewPage(false, false);
                curPage.getPageViewport().createSpan(true);
            } else if (pv.getCurrentSpan().hasMoreFlows()) {
                pv.getCurrentSpan().moveToNextFlow();
            } else {
                curPage = makeNewPage(false, false);
            }
            return;
        }
        log.debug("handling break-before after page " + currentPageNum 
            + " breakVal=" + breakVal);
        if (needBlankPageBeforeNew(breakVal)) {
            curPage = makeNewPage(true, false);
        }
        if (needNewPage(breakVal)) {
            curPage = makeNewPage(false, false);
        }
    }

    /**
     * Check if a blank page is needed to accomodate
     * desired even or odd page number.
     * @param breakVal - value of break-before or break-after trait.
     */
    private boolean needBlankPageBeforeNew(int breakVal) {
        if (breakVal == Constants.EN_PAGE || (curPage.getPageViewport().getPage().isEmpty())) {
            // any page is OK or we already have an empty page
            return false;
        } else {
            /* IF we are on the kind of page we need, we'll need a new page. */
            if (currentPageNum % 2 == 0) { // even page
                return (breakVal == Constants.EN_EVEN_PAGE);
            } else { // odd page
                return (breakVal == Constants.EN_ODD_PAGE);
            }
        }
    }

    /**
     * See if need to generate a new page
     * @param breakVal - value of break-before or break-after trait.
     */
    private boolean needNewPage(int breakVal) {
        if (curPage.getPageViewport().getPage().isEmpty()) {
            if (breakVal == Constants.EN_PAGE) {
                return false;
            } else if (currentPageNum % 2 == 0) { // even page
                return (breakVal == Constants.EN_ODD_PAGE);
            } else { // odd page
                return (breakVal == Constants.EN_EVEN_PAGE);
            }
        } else {
            return true;
        }
    }
    
    
    /**
     * <p>This class delivers Page instances. It also caches them as necessary.
     * </p>
     * <p>Additional functionality makes sure that surplus instances that are requested by the
     * page breaker are properly discarded, especially in situations where hard breaks cause
     * blank pages. The reason for that: The page breaker sometimes needs to preallocate 
     * additional pages since it doesn't know exactly until the end how many pages it really needs.
     * </p>
     */
    public class PageProvider {
        
        private Log log = LogFactory.getLog(PageProvider.class);

        /** Indices are evaluated relative to the first page in the page-sequence. */
        public static final int RELTO_PAGE_SEQUENCE = 0;
        /** Indices are evaluated relative to the first page in the current element list. */
        public static final int RELTO_CURRENT_ELEMENT_LIST = 1;
        
        private int startPageOfPageSequence;
        private int startPageOfCurrentElementList;
        private int startColumnOfCurrentElementList;
        private List cachedPages = new java.util.ArrayList();
        
        private int lastPageIndex = -1;
        private int indexOfCachedLastPage = -1;
        
        //Cache to optimize getAvailableBPD() calls
        private int lastRequestedIndex = -1;
        private int lastReportedBPD = -1;
        
        /**
         * Main constructor.
         * @param ps The page-sequence the provider operates on
         */
        public PageProvider(PageSequence ps) {
            this.startPageOfPageSequence = ps.getStartingPageNumber();
        }
        
        /**
         * The page breaker notifies the provider about the page number an element list starts
         * on so it can later retrieve PageViewports relative to this first page.
         * @param startPage the number of the first page for the element list.
         * @param startColumn the starting column number for the element list. 
         */
        public void setStartOfNextElementList(int startPage, int startColumn) {
            log.debug("start of the next element list is:"
                    + " page=" + startPage + " col=" + startColumn);
            this.startPageOfCurrentElementList = startPage - startPageOfPageSequence + 1;
            this.startColumnOfCurrentElementList = startColumn;
            //Reset Cache
            this.lastRequestedIndex = -1;
            this.lastReportedBPD = -1;
        }
        
        /**
         * Sets the index of the last page. This is done as soon as the position of the last page
         * is known or assumed.
         * @param index the index relative to the first page in the page-sequence
         */
        public void setLastPageIndex(int index) {
            this.lastPageIndex = index;
        }
        
        /**
         * Returns the available BPD for the part/page indicated by the index parameter.
         * The index is the part/page relative to the start of the current element list.
         * This method takes multiple columns into account.
         * @param index zero-based index of the requested part/page
         * @return the available BPD
         */
        public int getAvailableBPD(int index) {
            //Special optimization: There may be many equal calls by the BreakingAlgorithm
            if (this.lastRequestedIndex == index) {
                if (log.isTraceEnabled()) {
                    log.trace("getAvailableBPD(" + index + ") -> (cached) " + lastReportedBPD);
                }
                return this.lastReportedBPD;
            }
            int c = index;
            int pageIndex = 0;
            int colIndex = startColumnOfCurrentElementList;
            Page page = getPage(
                    false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
            while (c > 0) {
                colIndex++;
                if (colIndex >= page.getPageViewport().getCurrentSpan().getColumnCount()) {
                    colIndex = 0;
                    pageIndex++;
                    page = getPage(
                            false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
                }
                c--;
            }
            this.lastRequestedIndex = index;
            this.lastReportedBPD = page.getPageViewport().getBodyRegion().getRemainingBPD();
            if (log.isTraceEnabled()) {
                log.trace("getAvailableBPD(" + index + ") -> " + lastReportedBPD);
            }
            return this.lastReportedBPD;
        }
        
        /**
         * Returns the part index (0<x<partCount) which denotes the first part on the last page 
         * generated by the current element list.
         * @param partCount Number of parts determined by the breaking algorithm
         * @return the requested part index
         */
        public int getStartingPartIndexForLastPage(int partCount) {
            int result = 0;
            int idx = 0;
            int pageIndex = 0;
            int colIndex = startColumnOfCurrentElementList;
            Page page = getPage(
                    false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
            while (idx < partCount) {
                if ((colIndex >= page.getPageViewport().getCurrentSpan().getColumnCount())) {
                    colIndex = 0;
                    pageIndex++;
                    page = getPage(
                            false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
                    result = idx;
                }
                colIndex++;
                idx++;
            }
            return result;
        }

        /**
         * Returns a Page.
         * @param isBlank true if this page is supposed to be blank.
         * @param index Index of the page (see relativeTo)
         * @param relativeTo Defines which value the index parameter should be evaluated relative 
         * to. (One of PageProvider.RELTO_*)
         * @return the requested Page
         */
        public Page getPage(boolean isBlank, int index, int relativeTo) {
            if (relativeTo == RELTO_PAGE_SEQUENCE) {
                return getPage(isBlank, index);
            } else if (relativeTo == RELTO_CURRENT_ELEMENT_LIST) {
                int effIndex = startPageOfCurrentElementList + index;
                effIndex += startPageOfPageSequence - 1;
                return getPage(isBlank, effIndex);
            } else {
                throw new IllegalArgumentException(
                        "Illegal value for relativeTo: " + relativeTo);
            }
        }
        
        private Page getPage(boolean isBlank, int index) {
            boolean isLastPage = (lastPageIndex >= 0) && (index == lastPageIndex);
            if (log.isTraceEnabled()) {
                log.trace("getPage(" + index + " " + (isBlank ? "blank" : "non-blank") 
                        + (isLastPage ? " <LAST>" : "") + ")");
            }
            int intIndex = index - startPageOfPageSequence;
            if (log.isTraceEnabled()) {
                if (isBlank) {
                    log.trace("blank page requested: " + index);
                }
                if (isLastPage) {
                    log.trace("last page requested: " + index);
                }
            }
            while (intIndex >= cachedPages.size()) {
                if (log.isTraceEnabled()) {
                    log.trace("Caching " + index);
                }
                cacheNextPage(index, isBlank, isLastPage);
            }
            Page page = (Page)cachedPages.get(intIndex);
            boolean replace = false;
            if (page.getPageViewport().isBlank() != isBlank) {
                log.debug("blank condition doesn't match. Replacing PageViewport.");
                replace = true;
            }
            if ((isLastPage && indexOfCachedLastPage != intIndex)
                    || (!isLastPage && indexOfCachedLastPage >= 0)) {
                log.debug("last page condition doesn't match. Replacing PageViewport.");
                replace = true;
                indexOfCachedLastPage = (isLastPage ? intIndex : -1);
            }
            if (replace) {
                disardCacheStartingWith(intIndex);
                page = cacheNextPage(index, isBlank, isLastPage);
            }
            return page;
        }

        private void disardCacheStartingWith(int index) {
            while (index < cachedPages.size()) {
                this.cachedPages.remove(cachedPages.size() - 1);
                if (!pageSeq.goToPreviousSimplePageMaster()) {
                    log.warn("goToPreviousSimplePageMaster() on the first page called!");
                }
            }
        }
        
        private Page cacheNextPage(int index, boolean isBlank, boolean isLastPage) {
            try {
                String pageNumberString = pageSeq.makeFormattedPageNumber(index);
                SimplePageMaster spm = pageSeq.getNextSimplePageMaster(
                        index, (startPageOfPageSequence == index), isLastPage, isBlank);
                    
                Region body = spm.getRegion(FO_REGION_BODY);
                if (!pageSeq.getMainFlow().getFlowName().equals(body.getRegionName())) {
                    // this is fine by the XSL Rec (fo:flow's flow-name can be mapped to
                    // any region), but we don't support it yet.
                    throw new FOPException("Flow '" + pageSeq.getMainFlow().getFlowName()
                        + "' does not map to the region-body in page-master '"
                        + spm.getMasterName() + "'.  FOP presently "
                        + "does not support this.");
                }
                Page page = new Page(spm, index, pageNumberString, isBlank);
                //Set unique key obtained from the AreaTreeHandler
                page.getPageViewport().setKey(areaTreeHandler.generatePageViewportKey());
                page.getPageViewport().setForeignAttributes(spm.getForeignAttributes());
                cachedPages.add(page);
                return page;
            } catch (FOPException e) {
                //TODO Maybe improve. It'll mean to propagate this exception up several
                //methods calls.
                throw new IllegalStateException(e.getMessage());
            }
        }
        
    }

    /**
     * Act upon the force-page-count trait,
     * in relation to the initial-page-number trait of the following page-sequence.
     * @param nextPageSeqInitialPageNumber initial-page-number trait of next page-sequence
     */
    public void doForcePageCount(Numeric nextPageSeqInitialPageNumber) {

        int forcePageCount = pageSeq.getForcePageCount();

        // xsl-spec version 1.0   (15.oct 2001)
        // auto | even | odd | end-on-even | end-on-odd | no-force | inherit
        // auto:
        // Force the last page in this page-sequence to be an odd-page 
        // if the initial-page-number of the next page-sequence is even. 
        // Force it to be an even-page 
        // if the initial-page-number of the next page-sequence is odd. 
        // If there is no next page-sequence 
        // or if the value of its initial-page-number is "auto" do not force any page.
            

        // if force-page-count is auto then set the value of forcePageCount 
        // depending on the initial-page-number of the next page-sequence
        if (nextPageSeqInitialPageNumber != null && forcePageCount == Constants.EN_AUTO) {
            if (nextPageSeqInitialPageNumber.getEnum() != 0) {
                // auto | auto-odd | auto-even
                int nextPageSeqPageNumberType = nextPageSeqInitialPageNumber.getEnum();
                if (nextPageSeqPageNumberType == Constants.EN_AUTO_ODD) {
                    forcePageCount = Constants.EN_END_ON_EVEN;
                } else if (nextPageSeqPageNumberType == Constants.EN_AUTO_EVEN) {
                    forcePageCount = Constants.EN_END_ON_ODD;
                } else {   // auto
                    forcePageCount = Constants.EN_NO_FORCE;
                }
            } else { // <integer> for explicit page number
                int nextPageSeqPageStart = nextPageSeqInitialPageNumber.getValue();
                // spec rule
                nextPageSeqPageStart = (nextPageSeqPageStart > 0) ? nextPageSeqPageStart : 1;
                if (nextPageSeqPageStart % 2 == 0) {   // explicit even startnumber
                    forcePageCount = Constants.EN_END_ON_ODD;
                } else {    // explicit odd startnumber
                    forcePageCount = Constants.EN_END_ON_EVEN;
                }
            }
        }

        if (forcePageCount == Constants.EN_EVEN) {
            if ((currentPageNum - startPageNum + 1) % 2 != 0) { // we have a odd number of pages
                curPage = makeNewPage(true, false);
            }
        } else if (forcePageCount == Constants.EN_ODD) {
            if ((currentPageNum - startPageNum + 1) % 2 == 0) { // we have a even number of pages
                curPage = makeNewPage(true, false);
            }
        } else if (forcePageCount == Constants.EN_END_ON_EVEN) {
            if (currentPageNum % 2 != 0) { // we are now on a odd page
                curPage = makeNewPage(true, false);
            }
        } else if (forcePageCount == Constants.EN_END_ON_ODD) {
            if (currentPageNum % 2 == 0) { // we are now on a even page
                curPage = makeNewPage(true, false);
            }
        } else if (forcePageCount == Constants.EN_NO_FORCE) {
            // i hope: nothing special at all
        }

        if (curPage != null) {
            finishPage();
        }
    }
}
