/*
 * 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 java.util.ArrayList;
import java.util.Collections;
import java.util.List;

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

import org.apache.fop.area.Area;
import org.apache.fop.area.AreaTreeHandler;
import org.apache.fop.area.AreaTreeModel;
import org.apache.fop.area.LineArea;
import org.apache.fop.complexscripts.bidi.BidiResolver;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.pagination.PageSequence;
import org.apache.fop.fo.pagination.PageSequenceMaster;
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.StaticContent;
import org.apache.fop.layoutmgr.inline.ContentLayoutManager;
import org.apache.fop.traits.MinOptMax;

/**
 * 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 AbstractPageSequenceLayoutManager {

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

    private PageProvider pageProvider;

    private PageBreaker pageBreaker;

    /** Footnotes coming from repeated table headers, to be added before any other footnote. */
    private List<List<KnuthElement>> tableHeaderFootnotes;

    /** Footnotes coming from repeated table footers, to be added after any other footnote. */
    private List<List<KnuthElement>> tableFooterFootnotes;

    private int startIntrusionAdjustment;
    private int endIntrusionAdjustment;

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

    /** @return the PageProvider applicable to this page-sequence. */
    public PageProvider getPageProvider() {
        return this.pageProvider;
    }

    /**
     * @return the PageSequence being managed by this layout manager
     */
    protected PageSequence getPageSequence() {
        return (PageSequence)pageSeq;
    }

    /**
     * Provides access to this object
     * @return this PageSequenceLayoutManager instance
     */
    public PageSequenceLayoutManager getPSLM() {
        return this;
    }

    public FlowLayoutManager getFlowLayoutManager() {
        if (pageBreaker == null) {
            throw new IllegalStateException("This method can be called only during layout");
        }
        return pageBreaker.getCurrentChildLM();
    }

    /** {@inheritDoc} */
    public void activateLayout() {
        initialize();

        // perform step 5.8 of refinement process (Unicode BIDI Processing)
        if (areaTreeHandler.isComplexScriptFeaturesEnabled()) {
            BidiResolver.resolveInlineDirectionality(getPageSequence());
        }

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

        AreaTreeModel areaTreeModel = areaTreeHandler.getAreaTreeModel();
        org.apache.fop.area.PageSequence pageSequenceAreaObject
                = new org.apache.fop.area.PageSequence(title);
        transferExtensions(pageSequenceAreaObject);
        pageSequenceAreaObject.setLocale(getPageSequence().getLocale());
        areaTreeModel.startPageSequence(pageSequenceAreaObject);
        if (log.isDebugEnabled()) {
            log.debug("Starting layout");
        }

        boolean finished = false;
        while (!finished) {
            initialize();
            curPage = makeNewPage(false);

            pageBreaker = new PageBreaker(this);
            int flowBPD = getCurrentPV().getBodyRegion().getRemainingBPD();
            finished = pageBreaker.doLayout(flowBPD);
            pageProvider.skipPagePositionOnly = true;
        }

        finishPage();
    }

    public void initialize() {
        super.initialize();
        pageProvider.initialize();
    }

    /** {@inheritDoc} */
    public void finishPageSequence() {
        if (pageSeq.hasId()) {
            idTracker.signalIDProcessed(pageSeq.getId());
        }
        pageSeq.getRoot().notifyPageSequenceFinished(currentPageNum,
                (currentPageNum - startPageNum) + 1);
        areaTreeHandler.notifyPageSequenceFinished(pageSeq,
                (currentPageNum - startPageNum) + 1);
        getPageSequence().releasePageSequence();

        // If this sequence has a page sequence master so we must reset
        // it in preparation for the next sequence
        String masterReference = getPageSequence().getMasterReference();
        PageSequenceMaster pageSeqMaster
            = pageSeq.getRoot().getLayoutMasterSet().getPageSequenceMaster(masterReference);
        if (pageSeqMaster != null) {
            pageSeqMaster.reset();
        }

        if (log.isDebugEnabled()) {
            log.debug("Ending layout");
        }
    }

    /** {@inheritDoc} */
    protected Page createPage(int pageNumber, boolean isBlank) {
        return pageProvider.getPage(isBlank,
                pageNumber, PageProvider.RELTO_PAGE_SEQUENCE);
    }

    @Override
    protected Page makeNewPage(boolean isBlank) {
        return makeNewPage(isBlank, false);
    }

    protected Page makeNewPage(boolean isBlank, boolean emptyContent) {
        Page newPage = super.makeNewPage(isBlank);

        // Empty pages (pages that have been generated from a SPM that has an un-mapped flow name)
        // cannot layout areas from the main flow.  Blank pages can be created from empty pages.
        if (!isBlank && !emptyContent) {
            int i = 0;
            while (!flowNameEquals(newPage, i > 0)) {
                newPage = super.makeNewPage(isBlank);
                i++;
            }
        }

        return newPage;
    }

    private boolean flowNameEquals(Page newPage, boolean strict) {
        String psName = getPageSequence().getMainFlow().getFlowName();
        Region body = newPage.getSimplePageMaster().getRegion(FO_REGION_BODY);
        String name = body.getRegionName();
        if (strict && !name.equals(psName) && !name.equals(((RegionBody)body).getDefaultRegionName())
                && getPageSequence().hasPagePositionLast()) {
            throw new RuntimeException(
                    "The flow-name \"" + name + "\" could not be mapped to a region-name in the layout-master-set");
        }
        return psName.equals(name);
    }

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

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

    /** {@inheritDoc} */
    protected void finishPage() {
        // Layout side regions
        layoutSideRegion(FO_REGION_BEFORE);
        layoutSideRegion(FO_REGION_AFTER);
        layoutSideRegion(FO_REGION_START);
        layoutSideRegion(FO_REGION_END);

        super.finishPage();
    }

    /**
     * The last page number of the sequence may be incremented, as determined by the
     *  force-page-count formatting property semantics
     * @param lastPageNum number of sequence
     * @return the forced last page number of sequence
     */
    protected int getForcedLastPageNum(final int lastPageNum) {
        int forcedLastPageNum = lastPageNum;
        int relativeLastPage = lastPageNum - startPageNum + 1;
        if (getPageSequence().getForcePageCount() ==  Constants.EN_EVEN) {
            if (relativeLastPage % 2 != 0) {
                forcedLastPageNum++;
            }
        } else if (getPageSequence().getForcePageCount() ==  Constants.EN_ODD) {
            if (relativeLastPage % 2 == 0) {
                forcedLastPageNum++;
            }
        } else if (getPageSequence().getForcePageCount() ==  Constants.EN_END_ON_EVEN) {
            if (lastPageNum % 2 != 0) {
                forcedLastPageNum++;
            }
        } else if (getPageSequence().getForcePageCount() ==  Constants.EN_END_ON_ODD) {
            if (lastPageNum % 2 == 0) {
                forcedLastPageNum++;
            }
        }
        return forcedLastPageNum;
    }

    /**
     * Indicates whether the column/page at the given index is on the first page of this page sequence.
     *
     * @return {@code true} if the given part is on the first page of the sequence
     */
    boolean isOnFirstPage(int partIndex) {
        return pageProvider.isOnFirstPage(partIndex);
    }

    protected int getLastPageNumber() {
        return pageProvider.getLastPageIndex();
    }

    protected int getWidthOfCurrentPage() {
        if (curPage != null) {
            return (int) curPage.getPageViewport().getViewArea().getWidth();
        }
        return 0;
    }
    /**
     * Registers the given footnotes so that they can be added to the current page, before any other footnote.
     *
     * @param headerFootnotes footnotes coming from a repeated table header
     */
    public void addTableHeaderFootnotes(List<List<KnuthElement>> headerFootnotes) {
        if (tableHeaderFootnotes == null) {
            tableHeaderFootnotes = new ArrayList<List<KnuthElement>>();
        }
        tableHeaderFootnotes.addAll(headerFootnotes);
    }

    public List<List<KnuthElement>> getTableHeaderFootnotes() {
        return getTableFootnotes(tableHeaderFootnotes);
    }

    /**
     * Registers the given footnotes so that they can be added to the current page, after any other footnote.
     *
     * @param footerFootnotes footnotes coming from a repeated table footer
     */
    public void addTableFooterFootnotes(List<List<KnuthElement>> footerFootnotes) {
        if (tableFooterFootnotes == null) {
            tableFooterFootnotes = new ArrayList<List<KnuthElement>>();
        }
        tableFooterFootnotes.addAll(footerFootnotes);
    }

    public List<List<KnuthElement>> getTableFooterFootnotes() {
        return getTableFootnotes(tableFooterFootnotes);
    }

    private List<List<KnuthElement>> getTableFootnotes(List<List<KnuthElement>> tableFootnotes) {
        if (tableFootnotes == null) {
            List<List<KnuthElement>> emptyList = Collections.emptyList();
            return emptyList;
        } else {
            return tableFootnotes;
        }
    }

    /**
     * Clears the footnotes coming from repeated table headers/footers, in order to start
     * afresh for a new page.
     */
    public void clearTableHeadingFootnotes() {
        if (tableHeaderFootnotes != null) {
            tableHeaderFootnotes.clear();
        }
        if (tableFooterFootnotes != null) {
            tableFooterFootnotes.clear();
        }
    }

    public void setStartIntrusionAdjustment(int sia) {
        startIntrusionAdjustment = sia;
    }

    public void setEndIntrusionAdjustment(int eia) {
        endIntrusionAdjustment = eia;
    }

    public int getStartIntrusionAdjustment() {
        return startIntrusionAdjustment;
    }

    public int getEndIntrusionAdjustment() {
        return endIntrusionAdjustment;
    }

    public void recordEndOfFloat(int fHeight) {
        pageBreaker.handleEndOfFloat(fHeight);
    }

    public boolean handlingEndOfFloat() {
        return pageBreaker.handlingEndOfFloat();
    }

    public int getOffsetDueToFloat() {
        return pageBreaker.getOffsetDueToFloat();
    }

    public void recordStartOfFloat(int fHeight, int fYOffset) {
        pageBreaker.handleStartOfFloat(fHeight, fYOffset);
    }

    public boolean handlingStartOfFloat() {
        return pageBreaker.handlingStartOfFloat();
    }

    public int getFloatHeight() {
        return pageBreaker.getFloatHeight();
    }

    public int getFloatYOffset() {
        return pageBreaker.getFloatYOffset();
    }

    public int getCurrentColumnWidth() {
        int flowIPD = getCurrentPV().getCurrentSpan().getColumnWidth();
        flowIPD -= startIntrusionAdjustment + endIntrusionAdjustment;
        return flowIPD;
    }

    public void holdFootnotes(List fl, List ll, int tfl, int ifl, boolean fp, boolean nf, int fnfi, int fli,
            int fei, MinOptMax fsl, int pfli, int pfei) {
        if (fl != null && fl.size() > 0) {
            pageBreaker.holdFootnotes(fl, ll, tfl, ifl, fp, nf, fnfi, fli, fei, fsl, pfli, pfei);
        }
    }

    public void retrieveFootnotes(PageBreakingAlgorithm alg) {
        pageBreaker.retrieveFootones(alg);
    }
}
