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

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

import org.apache.fop.area.AreaTreeHandler;
import org.apache.fop.area.BodyRegion;
import org.apache.fop.area.PageViewport;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.pagination.PageProductionException;
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.SimplePageMaster;

/**
 * <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 implements Constants {

    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 boolean spanAllForCurrentElementList;
    private List<Page> cachedPages = new java.util.ArrayList<Page>();

    private int lastPageIndex = -1;
    private int indexOfCachedLastPage = -1;

    //Cache to optimize getAvailableBPD() calls
    private int lastRequestedIndex = -1;
    private int lastReportedBPD = -1;

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

    protected boolean skipPagePositionOnly;

    /**
     * Main constructor.
     * @param ath the area tree handler
     * @param ps The page-sequence the provider operates on
     */
    public PageProvider(AreaTreeHandler ath, PageSequence ps) {
        this.areaTreeHandler = ath;
        this.pageSeq = ps;
        this.startPageOfPageSequence = ps.getStartingPageNumber();
    }

    public void initialize() {
        cachedPages.clear();
    }

    /**
     * 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.
     * @param spanAll true if the current element list is for a column-spanning section
     */
    public void setStartOfNextElementList(int startPage, int startColumn, boolean spanAll) {
        if (log.isDebugEnabled()) {
            log.debug("start of the next element list is:"
                    + " page=" + startPage + " col=" + startColumn
                    + (spanAll ? ", column-spanning" : ""));
        }
        this.startPageOfCurrentElementList = startPage - startPageOfPageSequence + 1;
        this.startColumnOfCurrentElementList = startColumn;
        this.spanAllForCurrentElementList = spanAll;
        //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 pageIndexTmp = index;
        int pageIndex = 0;
        int colIndex = startColumnOfCurrentElementList;
        Page page = getPage(
                false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
        while (pageIndexTmp > 0) {
            colIndex++;
            if (colIndex >= page.getPageViewport().getCurrentSpan().getColumnCount()) {
                colIndex = 0;
                pageIndex++;
                page = getPage(false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
                BodyRegion br = page.getPageViewport().getBodyRegion();
                if (!pageSeq.getMainFlow().getFlowName().equals(br.getRegionName())) {
                    pageIndexTmp++;
                }
            }
            pageIndexTmp--;
        }
        this.lastRequestedIndex = index;
        this.lastReportedBPD = page.getPageViewport().getBodyRegion().getRemainingBPD();
        if (log.isTraceEnabled()) {
            log.trace("getAvailableBPD(" + index + ") -> " + lastReportedBPD);
        }
        return this.lastReportedBPD;
    }

    private static class Column {

        final Page page;

        final int pageIndex;

        final int colIndex;

        final int columnCount;

        Column(Page page, int pageIndex, int colIndex, int columnCount) {
            this.page = page;
            this.pageIndex = pageIndex;
            this.colIndex = colIndex;
            this.columnCount = columnCount;
        }

    }

    private Column getColumn(int index) {
        int columnCount = 0;
        int colIndex = startColumnOfCurrentElementList + index;
        int pageIndex = -1;
        Page page;
        do {
            colIndex -= columnCount;
            pageIndex++;
            page = getPage(false, pageIndex, RELTO_CURRENT_ELEMENT_LIST);
            if (page.getPageViewport().getPage() != null) {
                columnCount = page.getPageViewport().getCurrentSpan().getColumnCount();
            }
        } while (colIndex >= columnCount);
        return new Column(page, pageIndex, colIndex, columnCount);
    }

    /**
     * Compares the IPD of the given part with the following one.
     *
     * @param index index of the current part
     * @return a negative integer, zero or a positive integer as the current IPD is less
     * than, equal to or greater than the IPD of the following part
     */
    public int compareIPDs(int index) {
        Column column = getColumn(index);
        if (column.colIndex + 1 < column.columnCount) {
            // Next part is a column on same page => same IPD
            return 0;
        } else {
            Page nextPage = getPage(false, column.pageIndex + 1, RELTO_CURRENT_ELEMENT_LIST);
            return column.page.getPageViewport().getBodyRegion().getColumnIPD()
                    - nextPage.getPageViewport().getBodyRegion().getColumnIPD();
        }
    }

    /**
     * Checks if a break at the passed index would start a new page
     * @param index the index of the element before the break
     * @return  {@code true} if the break starts a new page
     */
    boolean startPage(int index) {
        return getColumn(index).colIndex == 0;
    }

    /**
     * Checks if a break at the passed index would end a page
     * @param index the index of the element before the break
     * @return  {@code true} if the break ends a page
     */
    boolean endPage(int index) {
        Column column = getColumn(index);
        return column.colIndex == column.columnCount - 1;
    }

    /**
     * Obtain the applicable column-count for the element at the
     * passed index
     * @param index the index of the element
     * @return  the number of columns
     */
    int getColumnCount(int index) {
        return getColumn(index).columnCount;
    }

    /**
     * Returns the part index (0&lt;x&lt;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 lastPartIndex = partCount - 1;
        return lastPartIndex - getColumn(lastPartIndex).colIndex;
    }

    Page getPageFromColumnIndex(int columnIndex) {
        return getColumn(columnIndex).page;
    }

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

    /**
     * Returns a Page.
     * @param isBlank true if the Page should be a blank one
     * @param index the Page's index
     * @return a Page instance
     */
    protected 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);
            }
        }
        if (intIndex > cachedPages.size()) {
            throw new UnsupportedOperationException("Cannot handle holes in page cache");
        } else if (intIndex == cachedPages.size()) {
            if (log.isTraceEnabled()) {
                log.trace("Caching " + index);
            }
            cacheNextPage(index, isBlank, isLastPage, this.spanAllForCurrentElementList);
        }
        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 (page.getPageViewport().getPage() != null
                && page.getPageViewport().getCurrentSpan().getColumnCount() == 1
                && !this.spanAllForCurrentElementList) {
            RegionBody rb = (RegionBody)page.getSimplePageMaster().getRegion(Region.FO_REGION_BODY);
            int colCount = rb.getColumnCount();
            if (colCount > 1) {
                log.debug("Span 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) {
            discardCacheStartingWith(intIndex);
            PageViewport oldPageVP = page.getPageViewport();
            page = cacheNextPage(index, isBlank, isLastPage, this.spanAllForCurrentElementList);
            PageViewport newPageVP = page.getPageViewport();
            newPageVP.replace(oldPageVP);
            this.areaTreeHandler.getIDTracker().replacePageViewPort(oldPageVP, newPageVP);
        }
        return page;
    }

    protected void discardCacheStartingWith(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, boolean spanAll) {
        String pageNumberString = pageSeq.makeFormattedPageNumber(index);
        boolean isFirstPage = (startPageOfPageSequence == index);
        SimplePageMaster spm = pageSeq.getNextSimplePageMaster(
                index, isFirstPage, isLastPage, isBlank);
        boolean isPagePositionOnly = pageSeq.hasPagePositionOnly() && !skipPagePositionOnly;
        if (isPagePositionOnly) {
            spm = pageSeq.getNextSimplePageMaster(index, isFirstPage, true, isBlank);
        }
        Page page = new Page(spm, index, pageNumberString, isBlank, spanAll, isPagePositionOnly);
        //Set unique key obtained from the AreaTreeHandler
        page.getPageViewport().setKey(areaTreeHandler.generatePageViewportKey());
        page.getPageViewport().setForeignAttributes(spm.getForeignAttributes());
        page.getPageViewport().setWritingModeTraits(pageSeq);
        cachedPages.add(page);
        if (isLastPage) {
            pageSeq.getRoot().setLastSeq(pageSeq);
        } else if (!isFirstPage) {
            pageSeq.getRoot().setLastSeq(null);
        }
        return page;
    }

    public int getIndexOfCachedLastPage() {
        return indexOfCachedLastPage;
    }

    public int getLastPageIndex() {
        return lastPageIndex;
    }

    public int getLastPageIPD() {
        int index = this.cachedPages.size();
        boolean isFirstPage = (startPageOfPageSequence == index);
        SimplePageMaster spm = pageSeq.getLastSimplePageMaster(index, isFirstPage, false);
        Page page = new Page(spm, index, "", false, false, false);
        if (pageSeq.getRoot().getLastSeq() != null && pageSeq.getRoot().getLastSeq() != pageSeq) {
            return -1;
        }
        return page.getPageViewport().getBodyRegion().getColumnIPD();
    }

    public int getCurrentIPD() {
        if (startPageOfCurrentElementList == 0) {
            return -1;
        }
        Page page = getPageFromColumnIndex(startColumnOfCurrentElementList);
        return page.getPageViewport().getBodyRegion().getColumnIPD();
    }

    public int getNextIPD() {
        pageSeq.setOnlyTryInfinite(true);
        try {
            int oldSize = cachedPages.size();
            Page page = getPageFromColumnIndex(startColumnOfCurrentElementList + 1);
            if (oldSize != cachedPages.size()) {
                cachedPages.remove(cachedPages.size() - 1);
            }
            return page.getPageViewport().getBodyRegion().getColumnIPD();
        } catch (PageProductionException e) {
            return getCurrentIPD();
        } finally {
            pageSeq.setOnlyTryInfinite(false);
        }
    }

    public int getCurrentColumnCount() {
        Page page = getPageFromColumnIndex(startColumnOfCurrentElementList);
        return page.getPageViewport().getCurrentSpan().getColumnCount();
    }

    /**
     * Indicates whether the column/page at the given index is on the first page of the page sequence.
     *
     * @return {@code true} if the given part is on the first page of the sequence
     */
    boolean isOnFirstPage(int partIndex) {
        Column column = getColumn(partIndex);
        return startPageOfCurrentElementList + column.pageIndex == startPageOfPageSequence;
    }

}
