/*
 * 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.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Stack;

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

import org.apache.fop.area.Area;
import org.apache.fop.area.BlockParent;
import org.apache.fop.fo.pagination.Flow;
import org.apache.fop.util.ListUtil;

/**
 * LayoutManager for an fo:flow object.
 * Its parent LM is the PageSequenceLayoutManager.
 * This LM is responsible for getting columns of the appropriate size
 * and filling them with block-level areas generated by its children.
 * TODO Reintroduce emergency counter (generate error to avoid endless loop)
 */
public class FlowLayoutManager extends BlockStackingLayoutManager {

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

    /** Array of areas currently being filled stored by area class */
    private final BlockParent[] currentAreas = new BlockParent[Area.CLASS_MAX];

    private boolean handlingFloat;

    /**
     * This is the top level layout manager.
     * It is created by the PageSequence FO.
     * @param pslm parent PageSequenceLayoutManager object
     * @param node Flow object
     */
    public FlowLayoutManager(PageSequenceLayoutManager pslm, Flow node) {
        super(node);
        setGeneratesBlockArea(true);
        setParent(pslm);
    }

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

    /**
     * Get a sequence of KnuthElements representing the content
     * of the node assigned to the LM.
     * @param context   the LayoutContext used to store layout information
     * @param alignment the desired text alignment
     * @param restartPosition   {@link Position} to restart from
     * @param restartLM {@link LayoutManager} to restart from
     * @return the list of KnuthElements
     * @see LayoutManager#getNextKnuthElements(LayoutContext,int)
     */
    List getNextKnuthElements(LayoutContext context, int alignment,
            Position restartPosition, LayoutManager restartLM) {

        List<ListElement> elements = new LinkedList<ListElement>();

        boolean isRestart = (restartPosition != null);
        // always reset in case of restart (exception: see below)
        boolean doReset = isRestart;
        LayoutManager currentChildLM;
        Stack<LayoutManager> lmStack = new Stack<LayoutManager>();
        if (isRestart) {
            currentChildLM = restartPosition.getLM();
            if (currentChildLM == null) {
                throw new IllegalStateException("Cannot find layout manager to restart from");
            }
            if (restartLM != null && restartLM.getParent() == this) {
                currentChildLM = restartLM;
            } else {
                while (currentChildLM.getParent() != this) {
                    lmStack.push(currentChildLM);
                    currentChildLM = currentChildLM.getParent();
                }
                doReset = false;
            }
            setCurrentChildLM(currentChildLM);
        } else {
            currentChildLM = getChildLM();
        }

        while (currentChildLM != null) {
            if (!isRestart || doReset) {
                if (doReset) {
                    currentChildLM.reset(); // TODO won't work with forced breaks
                }
                if (addChildElements(elements, currentChildLM, context, alignment,
                        null, null, null) != null) {
                    return elements;
                }
            } else {
                if (addChildElements(elements, currentChildLM, context, alignment, lmStack,
                        restartPosition, restartLM) != null) {
                    return elements;
                }
                // restarted; force reset as of next child
                doReset = true;
            }
            currentChildLM = getChildLM();
        }

        SpaceResolver.resolveElementList(elements);
        setFinished(true);

        assert !elements.isEmpty();
        return elements;
    }

    private List<ListElement> addChildElements(List<ListElement> elements,
            LayoutManager childLM, LayoutContext context, int alignment,
            Stack<LayoutManager> lmStack, Position position, LayoutManager restartAtLM) {
        if (handleSpanChange(childLM, context) && position == null) {
            SpaceResolver.resolveElementList(elements);
            return elements;
        }

        LayoutContext childLC = makeChildLayoutContext(context);
        List<ListElement> childElements
                = getNextChildElements(childLM, context, childLC, alignment, lmStack,
                    position, restartAtLM);
        if (elements.isEmpty()) {
            context.updateKeepWithPreviousPending(childLC.getKeepWithPreviousPending());
        }
        if (!elements.isEmpty()
                && !ElementListUtils.startsWithForcedBreak(childElements)) {
            addInBetweenBreak(elements, context, childLC);
        }
        context.updateKeepWithNextPending(childLC.getKeepWithNextPending());

        elements.addAll(childElements);

        if (ElementListUtils.endsWithForcedBreak(elements)) {
            // a descendant of this flow has break-before or break-after
            if (childLM.isFinished() && !hasNextChildLM()) {
                setFinished(true);
            }
            SpaceResolver.resolveElementList(elements);
            return elements;
        }
        return null;
    }

    private boolean handleSpanChange(LayoutManager childLM, LayoutContext context) {
        int span = EN_NONE;
        int disableColumnBalancing = EN_FALSE;
        if (childLM instanceof BlockLayoutManager) {
            span = ((BlockLayoutManager)childLM).getBlockFO().getSpan();
            disableColumnBalancing = ((BlockLayoutManager) childLM).getBlockFO()
                    .getDisableColumnBalancing();
        } else if (childLM instanceof BlockContainerLayoutManager) {
            span = ((BlockContainerLayoutManager)childLM).getBlockContainerFO().getSpan();
            disableColumnBalancing = ((BlockContainerLayoutManager) childLM).getBlockContainerFO()
                    .getDisableColumnBalancing();
        }

        int currentSpan = context.getCurrentSpan();
        if (currentSpan != span) {
            if (span == EN_ALL) {
                context.setDisableColumnBalancing(disableColumnBalancing);
            }
            log.debug("span change from " + currentSpan + " to " + span);
            context.signalSpanChange(span);
            return true;
        } else {
            return false;
        }
    }

    /**
     * Overridden to take into account the current page-master's
     * writing-mode
     * {@inheritDoc}
     */
    @Override
    protected LayoutContext makeChildLayoutContext(LayoutContext context) {
        LayoutContext childLC = LayoutContext.newInstance();
        childLC.setStackLimitBP(context.getStackLimitBP());
        childLC.setRefIPD(context.getRefIPD());
        childLC.setWritingMode(getCurrentPage().getSimplePageMaster().getWritingMode());
        return childLC;
    }

    /**
     * Overridden to wrap the child positions before returning the list
     * {@inheritDoc}
     */
    @Override
    protected List<ListElement> getNextChildElements(LayoutManager childLM, LayoutContext context,
            LayoutContext childLC, int alignment, Stack<LayoutManager> lmStack,
            Position restartPosition, LayoutManager restartLM) {

        List<ListElement> childElements;
        if (lmStack == null) {
            childElements = childLM.getNextKnuthElements(childLC, alignment);
        } else {
            childElements = childLM.getNextKnuthElements(childLC, alignment,
                    lmStack, restartPosition, restartLM);
        }
        assert !childElements.isEmpty();

        // "wrap" the Position inside each element
        List tempList = childElements;
        childElements = new LinkedList<ListElement>();
        wrapPositionElements(tempList, childElements);
        return childElements;
    }

    /** {@inheritDoc} */
    @Override
    public int negotiateBPDAdjustment(int adj, KnuthElement lastElement) {
        log.debug(" FLM.negotiateBPDAdjustment> " + adj);

        Position lastPosition = lastElement.getPosition();
        if (lastPosition instanceof NonLeafPosition) {
            // this element was not created by this FlowLM
            NonLeafPosition savedPos = (NonLeafPosition) lastPosition;
            lastElement.setPosition(savedPos.getPosition());
            int returnValue = ((BlockLevelLayoutManager)lastElement.getLayoutManager())
                    .negotiateBPDAdjustment(adj, lastElement);
            lastElement.setPosition(savedPos);
            log.debug(" FLM.negotiateBPDAdjustment> result " + returnValue);
            return returnValue;
        } else {
            return 0;
        }
    }

    /** {@inheritDoc} */
    @Override
    public void discardSpace(KnuthGlue spaceGlue) {
        log.debug(" FLM.discardSpace> ");

        Position gluePosition = spaceGlue.getPosition();
        if (gluePosition instanceof NonLeafPosition) {
            // this element was not created by this FlowLM
            NonLeafPosition savedPos = (NonLeafPosition) gluePosition;
            spaceGlue.setPosition(savedPos.getPosition());
            ((BlockLevelLayoutManager) spaceGlue.getLayoutManager()).discardSpace(spaceGlue);
            spaceGlue.setPosition(savedPos);
        }
    }

    /** {@inheritDoc} */
    @Override
    public Keep getKeepTogether() {
        return Keep.KEEP_AUTO;
    }

    /** {@inheritDoc} */
    @Override
    public Keep getKeepWithNext() {
        return Keep.KEEP_AUTO;
    }

    /** {@inheritDoc} */
    @Override
    public Keep getKeepWithPrevious() {
        return Keep.KEEP_AUTO;
    }

    /** {@inheritDoc} */
    @Override
    public List<KnuthElement> getChangedKnuthElements(List oldList, int alignment) {
        ListIterator<KnuthElement> oldListIterator = oldList.listIterator();
        KnuthElement returnedElement;
        List<KnuthElement> returnedList = new LinkedList<KnuthElement>();
        List<KnuthElement> returnList = new LinkedList<KnuthElement>();
        KnuthElement prevElement = null;
        KnuthElement currElement = null;
        int fromIndex = 0;

        // "unwrap" the Positions stored in the elements
        KnuthElement oldElement;
        while (oldListIterator.hasNext()) {
            oldElement = oldListIterator.next();
            if (oldElement.getPosition() instanceof NonLeafPosition) {
                // oldElement was created by a descendant of this FlowLM
                oldElement.setPosition((oldElement.getPosition()).getPosition());
            } else {
                // thisElement was created by this FlowLM, remove it
                oldListIterator.remove();
            }
        }
        // reset the iterator
        oldListIterator = oldList.listIterator();


        while (oldListIterator.hasNext()) {
            currElement = oldListIterator.next();
            if (prevElement != null
                && prevElement.getLayoutManager() != currElement.getLayoutManager()) {
                // prevElement is the last element generated by the same LM
                BlockLevelLayoutManager prevLM = (BlockLevelLayoutManager)
                                                 prevElement.getLayoutManager();
                BlockLevelLayoutManager currLM = (BlockLevelLayoutManager)
                                                 currElement.getLayoutManager();
                returnedList.addAll(prevLM.getChangedKnuthElements(
                        oldList.subList(fromIndex, oldListIterator.previousIndex()), alignment));
                fromIndex = oldListIterator.previousIndex();

                // there is another block after this one
                if (prevLM.mustKeepWithNext()
                    || currLM.mustKeepWithPrevious()) {
                    // add an infinite penalty to forbid a break between blocks
                    returnedList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false,
                            new Position(this), false));
                } else if (!ListUtil.getLast(returnedList).isGlue()) {
                    // add a null penalty to allow a break between blocks
                    returnedList.add(new KnuthPenalty(0, 0, false, new Position(this), false));
                }
            }
            prevElement = currElement;
        }
        if (currElement != null) {
            BlockLevelLayoutManager currLM = (BlockLevelLayoutManager)
                                             currElement.getLayoutManager();
            returnedList.addAll(currLM.getChangedKnuthElements(
                    oldList.subList(fromIndex, oldList.size()), alignment));
        }

        // "wrap" the Position stored in each element of returnedList
        // and add elements to returnList
        for (KnuthElement aReturnedList : returnedList) {
            returnedElement = aReturnedList;
            if (returnedElement.getLayoutManager() != this) {
                returnedElement.setPosition(
                        new NonLeafPosition(this, returnedElement.getPosition()));
            }
            returnList.add(returnedElement);
        }

        return returnList;
    }

    /** {@inheritDoc} */
    @Override
    public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) {
        AreaAdditionUtil.addAreas(this, parentIter, layoutContext);
        flush();
    }

    /**
     * Add child area to a the correct container, depending on its
     * area class. A Flow can fill at most one area container of any class
     * at any one time. The actual work is done by BlockStackingLM.
     *
     * @param childArea the area to add
     */
    @Override
    public void addChildArea(Area childArea) {
        if (childArea instanceof BlockParent && handlingFloat()) {
            BlockParent bp = (BlockParent) childArea;
            bp.setXOffset(getPSLM().getStartIntrusionAdjustment());
        }
        getParentArea(childArea);
        addChildToArea(childArea,
                          this.currentAreas[childArea.getAreaClass()]);
    }

    /** {@inheritDoc} */
    @Override
    public Area getParentArea(Area childArea) {
        BlockParent parentArea = null;
        int aclass = childArea.getAreaClass();

        if (aclass == Area.CLASS_NORMAL || aclass == Area.CLASS_SIDE_FLOAT) {
            parentArea = getCurrentPV().getCurrentFlow();
        } else if (aclass == Area.CLASS_BEFORE_FLOAT) {
            parentArea = getCurrentPV().getBodyRegion().getBeforeFloat();
        } else if (aclass == Area.CLASS_FOOTNOTE) {
            parentArea = getCurrentPV().getBodyRegion().getFootnote();
        } else {
            throw new IllegalStateException("(internal error) Invalid "
                    + "area class (" + aclass + ") requested.");
        }

        this.currentAreas[aclass] = parentArea;
        setCurrentArea(parentArea);
        return parentArea;
    }

    /**
     * Returns the IPD of the content area
     * @return the IPD of the content area
     */
    @Override
    public int getContentAreaIPD() {
        int flowIPD = getPSLM().getCurrentColumnWidth();
        return flowIPD;
    }

    /**
     * Returns the BPD of the content area
     * @return the BPD of the content area
     */
    @Override
    public int getContentAreaBPD() {
        return getCurrentPV().getBodyRegion().getBPD();
    }

    /** {@inheritDoc} */
    @Override
    public boolean isRestartable() {
        return true;
    }

    public void handleFloatOn() {
        handlingFloat = true;
    }

    public void handleFloatOff() {
        handlingFloat = false;
    }

    public boolean handlingFloat() {
        return handlingFloat;
    }
}

