/*
 * 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.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);
            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().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() {
        Page page = getPageFromColumnIndex(startColumnOfCurrentElementList);
        return page.getPageViewport().getBodyRegion().getColumnIPD();
    }

    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;
    }

}
