/*
 * 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.Block;
import org.apache.fop.area.LineArea;
import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager;
import org.apache.fop.layoutmgr.inline.LineLayoutManager;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.traits.SpaceVal;

/**
 * LayoutManager for a block FO.
 */
public class BlockLayoutManager extends SpacedBorderedPaddedBlockLayoutManager
        implements BreakOpportunity {

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

    private Block curBlockArea;

    /** Iterator over the child layout managers. */
    protected ListIterator<LayoutManager> proxyLMiter;

    private int lead = 12000;
    private Length lineHeight;
    private int follow = 2000;
    //private int middleShift = 0;

    /**
     * Creates a new BlockLayoutManager.
     * @param inBlock the block FO object to create the layout manager for.
     */
    public BlockLayoutManager(org.apache.fop.fo.flow.Block inBlock) {
        super(inBlock);
        proxyLMiter = new ProxyLMiter();
    }

    /** {@inheritDoc} */
    @Override
    public void initialize() {
        super.initialize();
        org.apache.fop.fo.flow.Block fo = getBlockFO();
        FontInfo fi = fo.getFOEventHandler().getFontInfo();
        FontTriplet[] fontkeys = fo.getCommonFont().getFontState(fi);
        Font initFont = fi.getFontInstance(fontkeys[0],
                getBlockFO().getCommonFont().fontSize.getValue(this));
        lead = initFont.getAscender();
        follow = -initFont.getDescender();
        //middleShift = -fs.getXHeight() / 2;
        lineHeight = fo.getLineHeight().getOptimum(this).getLength();
        startIndent = fo.getCommonMarginBlock().startIndent.getValue(this);
        endIndent = fo.getCommonMarginBlock().endIndent.getValue(this);
        foSpaceBefore = new SpaceVal(fo.getCommonMarginBlock().spaceBefore, this).getSpace();
        foSpaceAfter = new SpaceVal(fo.getCommonMarginBlock().spaceAfter, this).getSpace();
        // use optimum space values
        adjustedSpaceBefore = fo.getCommonMarginBlock().spaceBefore.getSpace()
                                    .getOptimum(this).getLength().getValue(this);
        adjustedSpaceAfter = fo.getCommonMarginBlock().spaceAfter.getSpace()
                                    .getOptimum(this).getLength().getValue(this);
    }

    @Override
    protected CommonBorderPaddingBackground getCommonBorderPaddingBackground() {
        return getBlockFO().getCommonBorderPaddingBackground();
    }

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

    /** {@inheritDoc} */
    @Override
    public List getNextKnuthElements(LayoutContext context, int alignment, Stack lmStack,
            Position restartPosition, LayoutManager restartAtLM) {
        resetSpaces();
        return super.getNextKnuthElements(
                context, alignment, lmStack, restartPosition, restartAtLM);
    }

    /**
     * Overridden to take into account that the childLM may be the block's
     * {@link LineLayoutManager}.
     * {@inheritDoc}
     */
    @Override
    protected List<ListElement> getNextChildElements(LayoutManager childLM, LayoutContext context,
           LayoutContext childLC, int alignment, Stack lmStack, Position restartPosition,
           LayoutManager restartAtLM) {

        childLC.copyPendingMarksFrom(context);

        if (childLM instanceof LineLayoutManager) {
            childLC.setRefIPD(getContentAreaIPD());
        } else {
            // nop; will have been properly set by makeChildLayoutContext()
        }

        if (childLM == this.childLMs.get(0)) {
            childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE);
            //Handled already by the parent (break collapsing, see above)
        }

        if (lmStack == null) {
            return childLM.getNextKnuthElements(childLC, alignment);
        } else {
            if (childLM instanceof LineLayoutManager) {
                assert (restartPosition instanceof LeafPosition);
                return ((LineLayoutManager) childLM).getNextKnuthElements(childLC, alignment,
                        (LeafPosition) restartPosition);
            } else {
                return childLM.getNextKnuthElements(childLC, alignment,
                        lmStack, restartPosition, restartAtLM);
            }
        }
    }

    private void resetSpaces() {
        this.discardBorderBefore = false;
        this.discardBorderAfter = false;
        this.discardPaddingBefore = false;
        this.discardPaddingAfter = false;
        this.effSpaceBefore = null;
        this.effSpaceAfter = null;
    }

    /**
     * Proxy iterator for Block LM.
     * This iterator creates and holds the complete list
     * of child LMs.
     * It uses fobjIter as its base iterator.
     * Block LM's createNextChildLMs uses this iterator
     * as its base iterator.
     */
    protected class ProxyLMiter extends LMiter {

        /**
         * Constructs a proxy iterator for Block LM.
         */
        public ProxyLMiter() {
            super(BlockLayoutManager.this);
            listLMs = new java.util.ArrayList<LayoutManager>(10);
        }

        /**
         * @return true if there are more child lms
         */
        public boolean hasNext() {
            return (curPos < listLMs.size()) || createNextChildLMs(curPos);
        }

        /**
         * @param pos ...
         * @return true if new child lms were added
         */
        protected boolean createNextChildLMs(int pos) {
            List<LayoutManager> newLMs = createChildLMs(pos + 1 - listLMs.size());
            if (newLMs != null) {
                listLMs.addAll(newLMs);
            }
            return pos < listLMs.size();
        }
    }

    /** {@inheritDoc} */
    @Override
    public boolean createNextChildLMs(int pos) {

        while (proxyLMiter.hasNext()) {
            LayoutManager lm = proxyLMiter.next();
            if (lm instanceof InlineLevelLayoutManager) {
                LineLayoutManager lineLM = createLineManager(lm);
                addChildLM(lineLM);
            } else {
                addChildLM(lm);
            }
            if (pos < childLMs.size()) {
                return true;
            }
        }
        return false;
    }

    /**
     * Create a new LineLM, and collect all consecutive
     * inline generating LMs as its child LMs.
     * @param firstlm First LM in new LineLM
     * @return the newly created LineLM
     */
    private LineLayoutManager createLineManager(LayoutManager firstlm) {
        LineLayoutManager llm;
        llm = new LineLayoutManager(getBlockFO(), lineHeight, lead, follow);
        List<LayoutManager> inlines = new java.util.ArrayList<LayoutManager>();
        inlines.add(firstlm);
        while (proxyLMiter.hasNext()) {
            LayoutManager lm = proxyLMiter.next();
            if (lm instanceof InlineLevelLayoutManager) {
                inlines.add(lm);
            } else {
                proxyLMiter.previous();
                break;
            }
        }
        llm.addChildLMs(inlines);
        return llm;
    }

    /** {@inheritDoc} */
    @Override
    public KeepProperty getKeepTogetherProperty() {
        return getBlockFO().getKeepTogether();
    }

    /** {@inheritDoc} */
    @Override
    public KeepProperty getKeepWithPreviousProperty() {
        return getBlockFO().getKeepWithPrevious();
    }

    /** {@inheritDoc} */
    @Override
    public KeepProperty getKeepWithNextProperty() {
        return getBlockFO().getKeepWithNext();
    }

    /** {@inheritDoc} */
    @Override
    public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) {
        getParentArea(null);

        // if this will create the first block area in a page
        // and display-align is after or center, add space before
        if (layoutContext.getSpaceBefore() > 0) {
            addBlockSpacing(0.0, MinOptMax.getInstance(layoutContext.getSpaceBefore()));
        }

        LayoutManager childLM;
        LayoutManager lastLM = null;
        LayoutContext lc = LayoutContext.offspringOf(layoutContext);
        lc.setSpaceAdjust(layoutContext.getSpaceAdjust());
        // set space after in the LayoutContext for children
        if (layoutContext.getSpaceAfter() > 0) {
            lc.setSpaceAfter(layoutContext.getSpaceAfter());
        }
        PositionIterator childPosIter;

        // "unwrap" the NonLeafPositions stored in parentIter
        // and put them in a new list;
        LinkedList<Position> positionList = new LinkedList<Position>();
        Position pos;
        Position firstPos = null;
        Position lastPos = null;
        while (parentIter.hasNext()) {
            pos = parentIter.next();
            //log.trace("pos = " + pos.getClass().getName() + "; " + pos);
            if (pos.getIndex() >= 0) {
                if (firstPos == null) {
                    firstPos = pos;
                }
                lastPos = pos;
            }
            Position innerPosition = pos;
            if (pos instanceof NonLeafPosition) {
                //Not all elements are wrapped
                innerPosition = pos.getPosition();
            }

            if (innerPosition != null
                    && (innerPosition.getLM() != this
                        || innerPosition instanceof MappingPosition)) {
                // innerPosition was created by another LM
                positionList.add(innerPosition);
                lastLM = innerPosition.getLM();
            }
        }

        addId();

        registerMarkers(true, isFirst(firstPos), isLast(lastPos));

        // the Positions in positionList were inside the elements
        // created by the LineLM
        childPosIter = new PositionIterator(positionList.listIterator());

        while ((childLM = childPosIter.getNextChildLM()) != null) {
            // set last area flag
            lc.setFlags(LayoutContext.LAST_AREA,
                    (layoutContext.isLastArea() && childLM == lastLM));
            lc.setStackLimitBP(layoutContext.getStackLimitBP());
            // Add the line areas to Area
            childLM.addAreas(childPosIter, lc);
        }

        registerMarkers(false, isFirst(firstPos), isLast(lastPos));

        TraitSetter.addSpaceBeforeAfter(curBlockArea, layoutContext.getSpaceAdjust(),
                effSpaceBefore, effSpaceAfter);
        flush();

        curBlockArea = null;
        resetSpaces();

        //Notify end of block layout manager to the PSLM
        checkEndOfLayout(lastPos);
    }

    /**
     * Return an Area which can contain the passed childArea. The childArea
     * may not yet have any content, but it has essential traits set.
     * In general, if the LayoutManager already has an Area it simply returns
     * it. Otherwise, it makes a new Area of the appropriate class.
     * It gets a parent area for its area by calling its parent LM.
     * Finally, based on the dimensions of the parent area, it initializes
     * its own area. This includes setting the content IPD and the maximum
     * BPD.
     * @param childArea area to get the parent area for
     * @return the parent area
     */
    @Override
    public Area getParentArea(Area childArea) {
        if (curBlockArea == null) {
            curBlockArea = new Block();

            curBlockArea.setIPD(super.getContentAreaIPD());

            curBlockArea.setBidiLevel(getBlockFO().getBidiLevelRecursive());

            TraitSetter.addBreaks(curBlockArea,
                    getBlockFO().getBreakBefore(), getBlockFO().getBreakAfter());

            // Must get dimensions from parent area
            //Don't optimize this line away. It can have ugly side-effects.
            /*Area parentArea =*/ parentLayoutManager.getParentArea(curBlockArea);

            // set traits
            TraitSetter.setProducerID(curBlockArea, getBlockFO().getId());
            TraitSetter.addBorders(curBlockArea,
                    getBlockFO().getCommonBorderPaddingBackground(),
                    discardBorderBefore, discardBorderAfter, false, false, this);
            TraitSetter.addPadding(curBlockArea,
                    getBlockFO().getCommonBorderPaddingBackground(),
                    discardPaddingBefore, discardPaddingAfter, false, false, this);
            TraitSetter.addMargins(curBlockArea,
                    getBlockFO().getCommonBorderPaddingBackground(),
                    startIndent, endIndent,
                    this);
            TraitSetter.setLayer(curBlockArea, getBlockFO().getLayer());

            curBlockArea.setLocale(getBlockFO().getCommonHyphenation().getLocale());
            curBlockArea.setLocation(FONode.getLocatorString(getBlockFO().getLocator()));
            setCurrentArea(curBlockArea); // ??? for generic operations
        }
        return curBlockArea;
    }

    /** {@inheritDoc} */
    @Override
    public void addChildArea(Area childArea) {
        if (curBlockArea != null) {
            if (childArea instanceof LineArea) {
                curBlockArea.addLineArea((LineArea) childArea);
            } else {
                curBlockArea.addBlock((Block) childArea);
            }
        }
    }

    /**
     * Force current area to be added to parent area.
     * {@inheritDoc}
     */
    @Override
    protected void flush() {
        if (curBlockArea != null) {
            TraitSetter.addBackground(curBlockArea,
                    getBlockFO().getCommonBorderPaddingBackground(),
                    this);
            super.flush();
        }
    }

    /**
     * convenience method that returns the Block node
     * @return the block node
     */
    protected org.apache.fop.fo.flow.Block getBlockFO() {
        return (org.apache.fop.fo.flow.Block) fobj;
    }

    // --------- Property Resolution related functions --------- //

    /**
     * Returns the IPD of the content area
     * @return the IPD of the content area
     */
    @Override
    public int getContentAreaIPD() {
        if (curBlockArea != null) {
            return curBlockArea.getIPD();
        }
        return super.getContentAreaIPD();
    }


    /**
     * Returns the BPD of the content area
     * @return the BPD of the content area
     */
    @Override
    public int getContentAreaBPD() {
        if (curBlockArea != null) {
            return curBlockArea.getBPD();
        }
        return -1;
    }

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

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

}
