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

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import org.apache.fop.area.Trait;
import org.apache.fop.area.inline.FilledArea;
import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.area.inline.Space;
import org.apache.fop.area.inline.TextArea;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.flow.Leader;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.layoutmgr.InlineKnuthSequence;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthGlue;
import org.apache.fop.layoutmgr.KnuthPenalty;
import org.apache.fop.layoutmgr.KnuthPossPosIter;
import org.apache.fop.layoutmgr.KnuthSequence;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.LeafPosition;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.PositionIterator;
import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.traits.MinOptMax;

/**
 * LayoutManager for the fo:leader formatting object
 */
public class LeaderLayoutManager extends LeafNodeLayoutManager {
    private Leader fobj;
    private Font font;

    private List contentList;
    private ContentLayoutManager clm;

    private int contentAreaIPD;

    /**
     * Constructor
     *
     * @param node the formatting object that creates this area
     */
    public LeaderLayoutManager(Leader node) {
        super(node);
        fobj = node;
    }

    /** {@inheritDoc} */
    public void initialize() {
        FontInfo fi = fobj.getFOEventHandler().getFontInfo();
        FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi);
        font = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this));
        // the property leader-alignment does not affect vertical positioning
        // (see section 7.21.1 in the XSL Recommendation)
        // setAlignment(node.getLeaderAlignment());
        setCommonBorderPaddingBackground(fobj.getCommonBorderPaddingBackground());
    }

    /**
     * Return the inline area for this leader.
     * @param context the layout context
     * @return the inline area
     */
    public InlineArea get(LayoutContext context) {
        return getLeaderInlineArea(context);
    }

    /**
     * Return the allocated IPD for this area.
     * @param refIPD the IPD of the reference area
     * @return the allocated IPD
     */
    protected MinOptMax getAllocationIPD(int refIPD) {
        return getLeaderAllocIPD(refIPD);
    }

    private MinOptMax getLeaderAllocIPD(int ipd) {
        // length of the leader
        int borderPaddingWidth = 0;
        if (commonBorderPaddingBackground != null) {
            borderPaddingWidth = commonBorderPaddingBackground.getIPPaddingAndBorder(false, this);
        }
        setContentAreaIPD(ipd - borderPaddingWidth);
        int opt = fobj.getLeaderLength().getOptimum(this).getLength().getValue(this)
                    - borderPaddingWidth;
        int min = fobj.getLeaderLength().getMinimum(this).getLength().getValue(this)
                    - borderPaddingWidth;
        int max = fobj.getLeaderLength().getMaximum(this).getLength().getValue(this)
                    - borderPaddingWidth;
        return MinOptMax.getInstance(min, opt, max);
    }

    private InlineArea getLeaderInlineArea(LayoutContext context) {
        InlineArea leaderArea = null;
        int level = fobj.getBidiLevel();
        if (fobj.getLeaderPattern() == EN_RULE) {
            if (fobj.getRuleStyle() != EN_NONE) {
                org.apache.fop.area.inline.Leader leader
                    = new org.apache.fop.area.inline.Leader();
                leader.setRuleStyle(fobj.getRuleStyle());
                leader.setRuleThickness(fobj.getRuleThickness().getValue(this));
                leaderArea = leader;
            } else {
                leaderArea = new Space();
                if (level >= 0) {
                    leaderArea.setBidiLevel(level);
                }
            }
            leaderArea.setBPD(fobj.getRuleThickness().getValue(this));
            leaderArea.addTrait(Trait.COLOR, fobj.getColor());
            if (level >= 0) {
                leaderArea.setBidiLevel(level);
            }
        } else if (fobj.getLeaderPattern() == EN_SPACE) {
            leaderArea = new Space();
            leaderArea.setBPD(fobj.getRuleThickness().getValue(this));
            if (level >= 0) {
                leaderArea.setBidiLevel(level);
            }
        } else if (fobj.getLeaderPattern() == EN_DOTS) {
            TextArea t = new TextArea();
            char dot = '.'; // userAgent.getLeaderDotCharacter();
            int width = font.getCharWidth(dot);
            int[] levels = (level < 0) ? null : new int[] {level};
            t.addWord("" + dot, width, null, levels, null, 0);
            t.setIPD(width);
            t.setBPD(width);
            t.setBaselineOffset(width);
            TraitSetter.addFontTraits(t, font);
            t.addTrait(Trait.COLOR, fobj.getColor());
            Space spacer = null;
            int widthLeaderPattern = fobj.getLeaderPatternWidth().getValue(this);
            if (widthLeaderPattern > width) {
                spacer = new Space();
                spacer.setIPD(widthLeaderPattern - width);
                if (level >= 0) {
                    spacer.setBidiLevel(level);
                }
                width = widthLeaderPattern;
            }
            FilledArea fa = new FilledArea();
            fa.setUnitWidth(width);
            fa.addChildArea(t);
            if (spacer != null) {
                fa.addChildArea(spacer);
            }
            fa.setBPD(t.getBPD());
            leaderArea = fa;
        } else if (fobj.getLeaderPattern() == EN_USECONTENT) {
            if (fobj.getChildNodes() == null) {
                InlineLevelEventProducer eventProducer = InlineLevelEventProducer.Provider.get(
                        getFObj().getUserAgent().getEventBroadcaster());
                eventProducer.leaderWithoutContent(this, getFObj().getLocator());
                return null;
            }

            // child FOs are assigned to the InlineStackingLM
            fobjIter = null;

            // get breaks then add areas to FilledArea
            FilledArea fa = new FilledArea();

            clm = new ContentLayoutManager(fa, this);
            addChildLM(clm);

            InlineLayoutManager lm;
            lm = new InlineLayoutManager(fobj);
            clm.addChildLM(lm);
            lm.initialize();

            LayoutContext childContext = LayoutContext.newInstance();
            childContext.setAlignmentContext(context.getAlignmentContext());
            contentList = clm.getNextKnuthElements(childContext, 0);
            int width = clm.getStackingSize();
            if (width != 0) {
                Space spacer = null;
                if (fobj.getLeaderPatternWidth().getValue(this) > width) {
                    spacer = new Space();
                    spacer.setIPD(fobj.getLeaderPatternWidth().getValue(this) - width);
                    if (level >= 0) {
                        spacer.setBidiLevel(level);
                    }
                    width = fobj.getLeaderPatternWidth().getValue(this);
                }
                fa.setUnitWidth(width);
                if (spacer != null) {
                    fa.addChildArea(spacer);
                }
                leaderArea = fa;
            } else {
                //Content collapsed to nothing, so use a space
                leaderArea = new Space();
                leaderArea.setBPD(fobj.getRuleThickness().getValue(this));
                leaderArea.setBidiLevel(fobj.getBidiLevelRecursive());
            }
        }

        assert leaderArea != null;
        leaderArea.setChangeBarList(getChangeBarList());

        TraitSetter.setProducerID(leaderArea, fobj.getId());
        return leaderArea;
     }

    /** {@inheritDoc} */
    public void addAreas(PositionIterator posIter, LayoutContext context) {
        if (fobj.getLeaderPattern() != EN_USECONTENT) {
            // use LeafNodeLayoutManager.addAreas()
            super.addAreas(posIter, context);
        } else {
            addId();

            widthAdjustArea(curArea, context);

            if (commonBorderPaddingBackground != null) {
                // Add border and padding to area
                TraitSetter.setBorderPaddingTraits(curArea,
                                                   commonBorderPaddingBackground,
                                                   false, false, this);
                TraitSetter.addBackground(curArea, commonBorderPaddingBackground, this);
            }

            // add content areas
            KnuthPossPosIter contentIter = new KnuthPossPosIter(contentList, 0, contentList.size());
            clm.addAreas(contentIter, context);

            parentLayoutManager.addChildArea(curArea);

            while (posIter.hasNext()) {
                posIter.next();
            }
        }
    }

    /** {@inheritDoc} */
    public List getNextKnuthElements(LayoutContext context, int alignment) {
        MinOptMax ipd;
        curArea = get(context);
        KnuthSequence seq = new InlineKnuthSequence();

        if (curArea == null) {
            setFinished(true);
            return null;
        }

        alignmentContext = new AlignmentContext(curArea.getBPD()
                                    , fobj.getAlignmentAdjust()
                                    , fobj.getAlignmentBaseline()
                                    , fobj.getBaselineShift()
                                    , fobj.getDominantBaseline()
                                    , context.getAlignmentContext());

        ipd = getAllocationIPD(context.getRefIPD());
        if (fobj.getLeaderPattern() == EN_USECONTENT && curArea instanceof FilledArea) {
            // If we have user supplied content make it fit if we can
            int unitWidth = ((FilledArea) curArea).getUnitWidth();
            if (ipd.getOpt() < unitWidth && unitWidth <= ipd.getMax()) {
                ipd = MinOptMax.getInstance(ipd.getMin(), unitWidth, ipd.getMax());
            }
        }

        // create the AreaInfo object to store the computed values
        areaInfo = new AreaInfo((short) 0, ipd, false, context.getAlignmentContext());
        curArea.setAdjustingInfo(ipd.getStretch(), ipd.getShrink(), 0);

        addKnuthElementsForBorderPaddingStart(seq);

        // node is a fo:Leader
        seq.add(new KnuthInlineBox(0, alignmentContext, new LeafPosition(this, -1), true));
        seq.add(new KnuthPenalty(0, KnuthElement.INFINITE, false,
                new LeafPosition(this, -1), true));
        if (alignment == EN_JUSTIFY || alignment == 0) {
            seq.add(new KnuthGlue(areaInfo.ipdArea, new LeafPosition(this, 0), false));
        } else {
            seq.add(new KnuthGlue(areaInfo.ipdArea.getOpt(), 0, 0,
                    new LeafPosition(this, 0), false));
        }
        seq.add(new KnuthInlineBox(0, alignmentContext, new LeafPosition(this, -1), true));

        addKnuthElementsForBorderPaddingEnd(seq);

        setFinished(true);
        return Collections.singletonList(seq);
    }

    /** {@inheritDoc} */
    public void hyphenate(Position pos, HyphContext hc) {
        // use the AbstractLayoutManager.hyphenate() null implementation
        super.hyphenate(pos, hc);
    }

    /** {@inheritDoc} */
    public boolean applyChanges(List oldList) {
        setFinished(false);
        return false;
    }

    /** {@inheritDoc} */
    public List getChangedKnuthElements(List oldList, int alignment) {
        if (isFinished()) {
            return null;
        }

        List returnList = new LinkedList();

        addKnuthElementsForBorderPaddingStart(returnList);

        returnList.add(new KnuthInlineBox(0, areaInfo.alignmentContext,
                                    new LeafPosition(this, -1), true));
        returnList.add(new KnuthPenalty(0, KnuthElement.INFINITE, false,
                                        new LeafPosition(this, -1), true));
        if (alignment == EN_JUSTIFY || alignment == 0) {
            returnList.add(new KnuthGlue(areaInfo.ipdArea, new LeafPosition(this, 0), false));
        } else {
            returnList.add(new KnuthGlue(areaInfo.ipdArea.getOpt(), 0, 0,
                    new LeafPosition(this, 0), false));
        }
        returnList.add(new KnuthInlineBox(0, areaInfo.alignmentContext,
                                    new LeafPosition(this, -1), true));

        addKnuthElementsForBorderPaddingEnd(returnList);

        setFinished(true);
        return returnList;
    }

    /** {@inheritDoc} */
    public int getBaseLength(int lengthBase, FObj fobj) {
        return getParent().getBaseLength(lengthBase, getParent().getFObj());
    }

    /**
     * Returns the IPD of the content area
     * @return the IPD of the content area
     */
    public int getContentAreaIPD() {
        return contentAreaIPD;
    }

    private void setContentAreaIPD(int contentAreaIPD) {
        this.contentAreaIPD = contentAreaIPD;
    }

    /** {@inheritDoc} */
    public void reset() {
        childLMs.clear();
        super.reset();
    }

}
