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

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.fop.area.inline.InlineArea;

import static org.apache.fop.fo.Constants.EN_CENTER;
import static org.apache.fop.fo.Constants.EN_END;
import static org.apache.fop.fo.Constants.EN_JUSTIFY;
import static org.apache.fop.fo.Constants.EN_START;

/**
 * The line area.
 * This is a line area that contains inline areas.
 */
public class LineArea extends Area {

    private static final long serialVersionUID = 7670235908329290684L;

    /**
     * this class stores information about line width and potential adjustments
     * that can be used in order to re-compute adjustement and / or indents when a
     * page-number or a page-number-citation is resolved
     */
    // @SuppressFBWarnings("SE_INNER_CLASS")
    private final class LineAdjustingInfo implements Serializable {

        private static final long serialVersionUID = -6103629976229458273L;

        private int lineAlignment;
        private int difference;
        private int availableStretch;
        private int availableShrink;
        private double variationFactor;
        private boolean bAddedToAreaTree;

        private LineAdjustingInfo(int alignment, int diff,
                                  int stretch, int shrink) {
            lineAlignment = alignment;
            difference = diff;
            availableStretch = stretch;
            availableShrink = shrink;
            variationFactor = 1.0;
            bAddedToAreaTree = false;
        }

        /** {@inheritDoc} */
        public String toString() {
            return getClass().getSimpleName()
                + ": diff=" + difference
                + ", variation=" + variationFactor
                + ", stretch=" + availableStretch
                + ", shrink=" + availableShrink;
        }
    }

    private LineAdjustingInfo adjustingInfo;

    // this class can contain the dominant char styling info
    // this means that many renderers can optimise a bit

    private List<InlineArea> inlineAreas = new ArrayList<InlineArea>();

    /**
     * default constructor:
     * nothing to do
     */
    public LineArea() {
    }

    /**
     * constructor with extra parameters:
     * a new LineAdjustingInfo object is created
     * @param alignment alignment of this line
     * @param diff      difference between content width and line width
     * @param stretch   the available stretch for any adjustments
     * @param shrink    the available shrink for any adjustments
     */
    public LineArea(int alignment, int diff,
                    int stretch, int shrink) {
        adjustingInfo = new LineAdjustingInfo(alignment, diff, stretch, shrink);
    }

    /**
     * Add a child area to this line area.
     *
     * @param childArea the inline child area to add
     */
    @Override
    public void addChildArea(Area childArea) {
        if (childArea instanceof InlineArea) {
            addInlineArea((InlineArea)childArea);
            // set the parent area for the child area
            ((InlineArea)childArea).setParentArea(this);
        }
    }

    /**
     * Add an inline child area to this line area.
     *
     * @param area the inline child area to add
     */
    public void addInlineArea(InlineArea area) {
        inlineAreas.add(area);
    }

    /**
     * <p>Set (en masse) the inline child areas of this line area.</p>
     * <p> Used by bidirectional processing after line area consituent reordering.</p>
     * @param inlineAreas the list of inline areas
     */
    public void setInlineAreas(List inlineAreas) {
        for (InlineArea ia : (Iterable<InlineArea>) inlineAreas) {
            Area pa = ia.getParentArea();
            if (pa == null) {
                ia.setParentArea(this);
            } else {
                assert pa == this;
            }
        }
        this.inlineAreas = inlineAreas;
    }

    /**
     * Get the inline child areas of this line area.
     *
     * @return the list of inline areas
     */
    public List getInlineAreas() {
        return inlineAreas;
    }

    /**
     * Get the start indent of this line area.
     * The start indent is used for offsetting the start of
     * the inline areas for alignment or other indents.
     *
     * @return the start indent value
     */
    public int getStartIndent() {
        if (hasTrait(Trait.START_INDENT)) {
            return getTraitAsInteger(Trait.START_INDENT);
        } else {
            return 0;
        }
    }

    /**
     * Get the end indent of this line area.
     * The end indent is used for offsetting the end of
     * the inline areas for alignment or other indents.
     *
     * @return the end indent value
     */
    public int getEndIndent() {
        if (hasTrait(Trait.END_INDENT)) {
            return getTraitAsInteger(Trait.END_INDENT);
        } else {
            return 0;
        }
    }

    /**
     * Updates the extents of the line area from its children.
     */
    public void updateExtentsFromChildren() {
        int ipd = 0;
        int bpd = 0;
        for (InlineArea inlineArea : inlineAreas) {
            ipd = Math.max(ipd, inlineArea.getAllocIPD());
            bpd += inlineArea.getAllocBPD();
        }
        setIPD(ipd);
        setBPD(bpd);
    }

    /**
     * receive notification about the ipd variation of a descendant area
     * and perform the needed adjustment, according to the alignment;
     * in particular:
     * <ul>
     *   <li>left-aligned text needs no adjustement;</li>
     *   <li>right-aligned text and centered text are handled locally,
     *       adjusting the indent of this LineArea;</li>
     *   <li>justified text requires a more complex adjustment, as the
     *       variation factor computed on the basis of the total
     *       stretch and shrink of the line must be applied in every
     *       descendant leaf areas (text areas and leader areas).</li>
     * </ul>
     * @param ipdVariation the difference between old and new ipd
     */
    public void handleIPDVariation(int ipdVariation) {
        int si = getStartIndent();
        int ei = getEndIndent();
        switch (adjustingInfo.lineAlignment) {
            case EN_START:
                // adjust end indent
                addTrait(Trait.END_INDENT, ei - ipdVariation);
                break;
            case EN_CENTER:
                // adjust start and end indents
                addTrait(Trait.START_INDENT, si - ipdVariation / 2);
                addTrait(Trait.END_INDENT, ei - ipdVariation / 2);
                break;
            case EN_END:
                // adjust start indent
                addTrait(Trait.START_INDENT, si - ipdVariation);
                break;
            case EN_JUSTIFY:
                // compute variation factor
                adjustingInfo.variationFactor *= (float) (adjustingInfo.difference - ipdVariation)
                        / adjustingInfo.difference;
                adjustingInfo.difference -= ipdVariation;
                // if the LineArea has already been added to the area tree,
                // call finalize(); otherwise, wait for the LineLM to call it
                if (adjustingInfo.bAddedToAreaTree) {
                    finish();
                }
                break;
            default:
                throw new RuntimeException();
        }
    }

    /**
     * apply the variation factor to all descendant areas
     * and destroy the AdjustingInfo object if there are
     * no UnresolvedAreas left
     */
    public void finish() {
        if (adjustingInfo.lineAlignment == EN_JUSTIFY) {
            if (log.isTraceEnabled()) {
                log.trace("Applying variation factor to justified line: " + adjustingInfo);
            }
            // justified line: apply the variation factor
            boolean bUnresolvedAreasPresent = false;
            // recursively apply variation factor to descendant areas
            for (InlineArea inlineArea : inlineAreas) {
                bUnresolvedAreasPresent |= inlineArea
                        .applyVariationFactor(adjustingInfo.variationFactor,
                                adjustingInfo.availableStretch,
                                adjustingInfo.availableShrink);
            }
            if (!bUnresolvedAreasPresent) {
                // there are no more UnresolvedAreas:
                // destroy the AdjustingInfo instance
                adjustingInfo = null;
            } else {
                // this method will be called again later:
                // the first time, it is called by the LineLM,
                // afterwards it must be called by the LineArea itself
                if (!adjustingInfo.bAddedToAreaTree) {
                    adjustingInfo.bAddedToAreaTree = true;
                }
                // reset the variation factor
                adjustingInfo.variationFactor = 1.0;
            }
        } else {
            // the line is not justified: the ipd variation has already
            // been handled, modifying the line indent
        }
    }

    public int getEffectiveIPD() {
        int maxIPD = 0;
        if (inlineAreas != null) {
            for (Area area : inlineAreas) {
                int effectiveIPD = area.getEffectiveIPD();
                if (effectiveIPD > maxIPD) {
                    maxIPD = effectiveIPD;
                }
            }
        }
        return maxIPD;
    }

}

