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

import org.apache.fop.fo.Constants;
import org.apache.fop.traits.WritingModeTraitsGetter;

/**
 * The span-reference-area.
 * This is a block-area with 0 border and padding that is stacked
 * within the main-reference-area
 * This object holds one or more normal-flow-reference-area children
 * based on the column-count trait in effect for this span.
 * See fo:region-body definition in the XSL Rec for more information.
 */
public class Span extends Area {

    private static final long serialVersionUID = -5551430053660081549L;

    // the list of flow reference areas in this span area
    private List<NormalFlow> flowAreas;
    private int colCount;
    private int colGap;
    private int colWidth; // width for each normal flow, calculated value
    private int curFlowIdx;  // n-f-r-a currently being processed, zero-based

    /**
     * Create a span area with the number of columns for this span area.
     *
     * @param colCount the number of columns in the span
     * @param colGap the column gap between each column
     * @param ipd the total ipd of the span
     */
    public Span(int colCount, int colGap, int ipd) {
        addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
        this.colCount = colCount;
        this.colGap = colGap;
        this.ipd = ipd;
        curFlowIdx = 0;
        createNormalFlows();
    }

    /**
     * Create the normal flows for this Span
     */
    private void createNormalFlows() {
        flowAreas = new java.util.ArrayList<NormalFlow>(colCount);
        colWidth = (ipd - ((colCount - 1) * colGap)) / colCount;

        for (int i = 0; i < colCount; i++) {
            NormalFlow newFlow = new NormalFlow(colWidth);
            flowAreas.add(newFlow);
        }
    }

    /**
     * Get the column count for this span area.
     *
     * @return the number of columns defined for this span area
     */
    public int getColumnCount() {
        return colCount;
    }

    /**
     * Get the width of a single column within this Span
     *
     * @return the width of a single column
     */
    public int getColumnWidth() {
        return colWidth;
    }

    /**
     * Get the height of this span area.
     *
     * @return the height of this span area
     */
    public int getHeight() {
        return getBPD();
    }


    /**
     * Get the normal flow area for a particular column.
     *
     * @param colRequested the zero-based column number of the flow
     * @return the flow area for the requested column
     */
    public NormalFlow getNormalFlow(int colRequested) {
        if (colRequested >= 0 && colRequested < colCount) {
            return flowAreas.get(colRequested);
        } else { // internal error
            throw new IllegalArgumentException("Invalid column number "
                    + colRequested + " requested; only 0-" + (colCount - 1)
                    + " available.");
        }
    }

    /**
     * Get the NormalFlow area currently being processed
     *
     * @return the current NormalFlow
     */
    public NormalFlow getCurrentFlow() {
        return getNormalFlow(curFlowIdx);
    }

    /** @return the index of the current normal flow */
    public int getCurrentFlowIndex() {
        return curFlowIdx;
    }

    /**
     * Indicate to the Span that the next column is being
     * processed.
     *
     * @return the new NormalFlow (in the next column)
     */
    public NormalFlow moveToNextFlow() {
        if (hasMoreFlows()) {
            curFlowIdx++;
            return getNormalFlow(curFlowIdx);
        } else {
            throw new IllegalStateException("(Internal error.) No more flows left in span.");
        }
    }

    /**
     * Indicates if the Span has unprocessed flows.
     *
     * @return true if Span can increment to the next flow,
     * false otherwise.
     */
    public boolean hasMoreFlows() {
        return (curFlowIdx < colCount - 1);
    }

    /**
     * Called to notify the span that all its flows have been fully generated so it can update
     * its own BPD extent.
     */
    public void notifyFlowsFinished() {
        int maxFlowBPD = Integer.MIN_VALUE;
        for (int i = 0; i < colCount; i++) {
            maxFlowBPD = Math.max(maxFlowBPD, getNormalFlow(i).getAllocBPD());
        }
        bpd = maxFlowBPD;
    }

    /**
     * Indicates whether any child areas have been added to this span area.
     *
     * This is achieved by looping through each flow.
     * @return true if no child areas have been added yet.
     */
    public boolean isEmpty() {
        int areaCount = 0;
        for (int i = 0; i < getColumnCount(); i++) {
            NormalFlow flow = getNormalFlow(i);
            if (flow != null) {
                if (flow.getChildAreas() != null) {
                    areaCount += flow.getChildAreas().size();
                }
            }
        }
        return (areaCount == 0);
    }

    /**
     * Sets the writing mode traits for the main reference area of
     * this span area.
     * @param wmtg a WM traits getter
     */
    public void setWritingModeTraits(WritingModeTraitsGetter wmtg) {
        switch (wmtg.getColumnProgressionDirection().getEnumValue()) {
        case Constants.EN_RL:
            setBidiLevel(1);
            for (Iterator<NormalFlow> it = flowAreas.iterator(); it.hasNext();) {
                it.next().setBidiLevel(1);
            }
            break;
        default:
            resetBidiLevel();
            for (Iterator<NormalFlow> it = flowAreas.iterator(); it.hasNext();) {
                it.next().resetBidiLevel();
            }
            break;
        }
    }

    /** {@inheritDoc} */
    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer(super.toString());
        if (colCount > 1) {
            sb.append(" {colCount=").append(colCount);
            sb.append(", colWidth=").append(colWidth);
            sb.append(", curFlowIdx=").append(this.curFlowIdx);
            sb.append("}");
        }
        return sb.toString();
    }

}

