/*
 * 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.Iterator;
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
     */
    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 (Iterator<InlineArea> it = inlineAreas.iterator(); it.hasNext();) {
            InlineArea ia = it.next();
            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 (int i = 0, len = inlineAreas.size(); i < len; i++) {
            ipd = Math.max(ipd, inlineAreas.get(i).getAllocIPD());
            bpd += inlineAreas.get(i).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 (int i = 0, len = inlineAreas.size(); i < len; i++) {
                bUnresolvedAreasPresent |= inlineAreas.get(i)
                        .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
        }
    }
}

