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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.xmlgraphics.util.QName;

import org.apache.fop.area.Area;
import org.apache.fop.area.AreaTreeObject;
import org.apache.fop.area.PageViewport;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.flow.Marker;
import org.apache.fop.fo.flow.RetrieveMarker;

/**
 * The base class for most LayoutManagers.
 */
public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager implements Constants {

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

    /** Parent LayoutManager for this LayoutManager */
    protected LayoutManager parentLayoutManager;
    /** List of child LayoutManagers */
    protected List<LayoutManager> childLMs;
    /** Iterator for child LayoutManagers */
    protected ListIterator fobjIter;
    /** Marker map for markers related to this LayoutManager */
    private Map<String, Marker> markers;

    /** True if this LayoutManager has handled all of its content. */
    private boolean isFinished;

    /** child LM during getNextKnuthElement phase */
    protected LayoutManager curChildLM;

    /** child LM iterator during getNextKnuthElement phase */
    protected ListIterator<LayoutManager> childLMiter;

    private int lastGeneratedPosition = -1;
    private int smallestPosNumberChecked = Integer.MAX_VALUE;

    private boolean preserveChildrenAtEndOfLayout;

    /**
     * Abstract layout manager.
     */
    public AbstractLayoutManager() {
    }

    /**
     * Abstract layout manager.
     *
     * @param fo the formatting object for this layout manager
     */
    public AbstractLayoutManager(FObj fo) {
        super(fo);
        markers = fo.getMarkers();
        fobjIter = fo.getChildNodes();
        childLMiter = new LMiter(this);
    }

    /** {@inheritDoc} */
    public void setParent(LayoutManager lm) {
        this.parentLayoutManager = lm;
    }

    /** {@inheritDoc} */
    public LayoutManager getParent() {
        return this.parentLayoutManager;
    }

    /** {@inheritDoc} */
    public void initialize() {
        // Empty
    }

    /**
     * Return currently active child LayoutManager or null if
     * all children have finished layout.
     * Note: child must implement LayoutManager! If it doesn't, skip it
     * and print a warning.
     * @return the current child LayoutManager
     */
    protected LayoutManager getChildLM() {
        if (curChildLM != null && !curChildLM.isFinished()) {
            return curChildLM;
        }
        if (childLMiter.hasNext()) {
            curChildLM = childLMiter.next();
            curChildLM.initialize();
            return curChildLM;
        }
        return null;
    }

    /**
     * Set currently active child layout manager.
     * @param childLM the child layout manager
     */
    protected void setCurrentChildLM(LayoutManager childLM) {
        curChildLM = childLM;
        childLMiter = new LMiter(this);
        do {
            curChildLM = childLMiter.next();
        } while (curChildLM != childLM);
    }

    /**
     * Return indication if getChildLM will return another LM.
     * @return true if another child LM is still available
     */
    protected boolean hasNextChildLM() {
        return childLMiter.hasNext();
    }

    /**
     * Tell whether this LayoutManager has handled all of its content.
     * @return True if there are no more break possibilities,
     * ie. the last one returned represents the end of the content.
     */
    public boolean isFinished() {
        return isFinished;
    }

    /**
     * Set the flag indicating the LayoutManager has handled all of its content.
     * @param fin the flag value to be set
     */
    public void setFinished(boolean fin) {
        isFinished = fin;
    }

    /** {@inheritDoc} */
    public void addAreas(PositionIterator posIter, LayoutContext context) {
    }

    /** {@inheritDoc} */
    public List getNextKnuthElements(LayoutContext context, int alignment) {
        log.warn("null implementation of getNextKnuthElements() called!");
        setFinished(true);
        return null;
    }

    /** {@inheritDoc} */
    public List getChangedKnuthElements(List oldList, int alignment) {
        log.warn("null implementation of getChangeKnuthElement() called!");
        return null;
    }

    /**
     * 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 the child area for which the parent area is wanted
     * @return the parent area for the given child
     */
    public Area getParentArea(Area childArea) {
        return null;
    }

    /**
     * Add a child area to the current area. If this causes the maximum
     * dimension of the current area to be exceeded, the parent LM is called
     * to add it.
     * @param childArea the child area to be added
     */
    public void addChildArea(Area childArea) {
    }

    /**
     * Create the LM instances for the children of the
     * formatting object being handled by this LM.
     * @param size the requested number of child LMs
     * @return the list with the preloaded child LMs
     */
    protected List<LayoutManager> createChildLMs(int size) {
        if (fobjIter == null) {
            return null;
        }
        List<LayoutManager> newLMs = new ArrayList<LayoutManager>(size);
        while (fobjIter.hasNext() && newLMs.size() < size) {
            Object theobj = fobjIter.next();
            if (theobj instanceof FONode) {
                FONode foNode = (FONode) theobj;
                if (foNode instanceof RetrieveMarker) {
                    foNode = getPSLM().resolveRetrieveMarker(
                        (RetrieveMarker) foNode);
                }
                if (foNode != null) {
                    getPSLM().getLayoutManagerMaker()
                        .makeLayoutManagers(foNode, newLMs);
                }
            }
        }
        return newLMs;
    }

    /** {@inheritDoc} */
    public PageSequenceLayoutManager getPSLM() {
        return parentLayoutManager.getPSLM();
    }

    /**
     * @see PageSequenceLayoutManager#getCurrentPage()
     * @return the {@link Page} instance corresponding to the current page
     */
    public Page getCurrentPage() {
        return getPSLM().getCurrentPage();
    }

    /** @return the current page viewport */
    public PageViewport getCurrentPV() {
        return getPSLM().getCurrentPage().getPageViewport();
    }

    /** {@inheritDoc} */
    public boolean createNextChildLMs(int pos) {
        List<LayoutManager> newLMs = createChildLMs(pos + 1 - childLMs.size());
        addChildLMs(newLMs);
        return pos < childLMs.size();
    }

    /** {@inheritDoc} */
    public List<LayoutManager> getChildLMs() {
        if (childLMs == null) {
            childLMs = new java.util.ArrayList<LayoutManager>(10);
        }
        return childLMs;
    }

    /** {@inheritDoc} */
    public void addChildLM(LayoutManager lm) {
        if (lm == null) {
            return;
        }
        lm.setParent(this);
        if (childLMs == null) {
            childLMs = new java.util.ArrayList<LayoutManager>(10);
        }
        childLMs.add(lm);
        if (log.isTraceEnabled()) {
            log.trace(this.getClass().getName()
                    + ": Adding child LM " + lm.getClass().getName());
        }
    }

    /** {@inheritDoc} */
    public void addChildLMs(List newLMs) {
        if (newLMs == null || newLMs.size() == 0) {
            return;
        }
        for (LayoutManager newLM : (Iterable<LayoutManager>) newLMs) {
            addChildLM(newLM);
        }
    }

    /**
     * Adds a Position to the Position participating in the first|last determination by assigning
     * it a unique position index.
     * @param pos the Position
     * @return the same Position but with a position index
     */
    public Position notifyPos(Position pos) {
        if (pos.getIndex() >= 0) {
            throw new IllegalStateException("Position already got its index");
        }

        pos.setIndex(++lastGeneratedPosition);
        return pos;
    }

    private void verifyNonNullPosition(Position pos) {
        if (pos == null || pos.getIndex() < 0) {
            throw new IllegalArgumentException(
                    "Only non-null Positions with an index can be checked");
        }
    }

    /**
     * Indicates whether the given Position is the first area-generating Position of this LM.
     * @param pos the Position (must be one with a position index)
     * @return True if it is the first Position
     */
    public boolean isFirst(Position pos) {
        //log.trace("isFirst() smallestPosNumberChecked=" + smallestPosNumberChecked + " " + pos);
        verifyNonNullPosition(pos);
        if (pos.getIndex() == this.smallestPosNumberChecked) {
            return true;
        } else if (pos.getIndex() < this.smallestPosNumberChecked) {
            this.smallestPosNumberChecked = pos.getIndex();
            return true;
        } else {
            return false;
        }
    }

    /**
     * Indicates whether the given Position is the last area-generating Position of this LM.
     * @param pos the Position (must be one with a position index)
     * @return True if it is the last Position
     */
    public boolean isLast(Position pos) {
        verifyNonNullPosition(pos);
        return (pos.getIndex() == this.lastGeneratedPosition
                && isFinished());
    }

    public boolean hasLineAreaDescendant() {
        if (childLMs == null || childLMs.isEmpty()) {
            return false;
        } else {
            for (LayoutManager childLM : childLMs) {
                if (childLM.hasLineAreaDescendant()) {
                    return true;
                }
            }
        }
        return false;
    }

    public int getBaselineOffset() {
        if (childLMs != null) {
            for (LayoutManager childLM : childLMs) {
                if (childLM.hasLineAreaDescendant()) {
                    return childLM.getBaselineOffset();
                }
            }
        }
        throw newNoLineAreaDescendantException();
    }

    protected IllegalStateException newNoLineAreaDescendantException() {
        return new IllegalStateException("getBaselineOffset called on an object that has no line-area descendant");
    }

    /**
     * Transfers foreign attributes from the formatting object to the area.
     * @param targetArea the area to set the attributes on
     */
    protected void transferForeignAttributes(AreaTreeObject targetArea) {
        Map<QName, String> atts = fobj.getForeignAttributes();
        targetArea.setForeignAttributes(atts);
    }

    /**
     * Transfers extension attachments from the formatting object to the area.
     * @param targetArea the area to set the extensions on
     */
    protected void transferExtensionAttachments(AreaTreeObject targetArea) {
        if (fobj.hasExtensionAttachments()) {
            targetArea.setExtensionAttachments(fobj.getExtensionAttachments());
        }
    }

    /**
     * Transfers extensions (foreign attributes and extension attachments) from
     * the formatting object to the area.
     * @param targetArea the area to set the extensions on
     */
    protected void transferExtensions(AreaTreeObject targetArea) {
        transferForeignAttributes(targetArea);
        transferExtensionAttachments(targetArea);
    }

    /**
     * Registers the FO's markers on the current PageViewport, and if applicable on the parent TableLM.
     *
     * @param isStarting    boolean indicating whether the markers qualify as 'starting'
     * @param isFirst   boolean indicating whether the markers qualify as 'first'
     * @param isLast    boolean indicating whether the markers qualify as 'last'
     */
    protected void registerMarkers(boolean isStarting, boolean isFirst, boolean isLast) {
        if (this.markers != null) {
            getCurrentPV().registerMarkers(
                    this.markers,
                    isStarting,
                    isFirst,
                    isLast);
            possiblyRegisterMarkersForTables(markers, isStarting, isFirst, isLast);
        }
    }

    /**
     * Registers the FO's id on the current PageViewport
     */
    protected void addId() {
        if (fobj != null) {
            getPSLM().addIDToPage(fobj.getId());
        }
    }

    /**
     * Notifies the {@link PageSequenceLayoutManager} that layout
     * for this LM has ended.
     */
    protected void notifyEndOfLayout() {
        if (fobj != null) {
            getPSLM().notifyEndOfLayout(fobj.getId());
        }
    }

    /**
     * Checks to see if the incoming {@link Position}
     * is the last one for this LM, and if so, calls
     * {@link #notifyEndOfLayout()} and cleans up.
     *
     * @param pos   the {@link Position} to check
     */
    protected void checkEndOfLayout(Position pos) {
        if (pos != null
            && pos.getLM() == this
            && this.isLast(pos)) {

            notifyEndOfLayout();

            if (!preserveChildrenAtEndOfLayout) {
                // References to the child LMs are no longer needed
                childLMs = null;
                curChildLM = null;
                childLMiter = null;
            }

            /* markers that qualify have been transferred to the page
             */
            markers = null;

            /* References to the FO's children can be released if the
             * LM is a descendant of the FlowLM. For static-content
             * the FO may still be needed on following pages.
             */
            LayoutManager lm = this.parentLayoutManager;
            while (!(lm instanceof FlowLayoutManager
                        || lm instanceof PageSequenceLayoutManager)) {
                lm = lm.getParent();
            }
            if (lm instanceof FlowLayoutManager && !preserveChildrenAtEndOfLayout) {
                fobj.clearChildNodes();
                fobjIter = null;
            }
        }
    }

    /*
     * Preserves the children LMs at the end of layout. This is necessary if the layout is expected to be
     * repeated, as when using retrieve-table-markers.
     */
    public void preserveChildrenAtEndOfLayout() {
        preserveChildrenAtEndOfLayout = true;
    }

    /** {@inheritDoc} */
    @Override
    public String toString() {
        return (super.toString() + (fobj != null ? "{fobj = " + fobj.toString() + "}" : ""));
    }

    /** {@inheritDoc} */
    @Override
    public void reset() {
        isFinished = false;
        curChildLM = null;
        childLMiter = new LMiter(this);
        /* Reset all the children LM that have been created so far. */
        for (LayoutManager childLM : getChildLMs()) {
            childLM.reset();
        }
        if (fobj != null) {
            markers = fobj.getMarkers();
        }
        lastGeneratedPosition = -1;
    }

    public void recreateChildrenLMs() {
        childLMs = new ArrayList();
        isFinished = false;
        if (fobj == null) {
            return;
        }
        fobjIter = fobj.getChildNodes();
        int position = 0;
        while (createNextChildLMs(position++)) {
            //
        }
        childLMiter = new LMiter(this);
        for (LMiter iter = new LMiter(this); iter.hasNext();) {
            AbstractBaseLayoutManager alm = (AbstractBaseLayoutManager) iter.next();
            alm.initialize();
            alm.recreateChildrenLMs();
            alm.preserveChildrenAtEndOfLayout();
        }
        curChildLM = getChildLM();
    }

    protected void possiblyRegisterMarkersForTables(Map<String, Marker> markers, boolean isStarting,
            boolean isFirst, boolean isLast) {
        LayoutManager lm = this.parentLayoutManager;
        if (lm instanceof FlowLayoutManager || lm instanceof PageSequenceLayoutManager
                || !(lm instanceof AbstractLayoutManager)) {
            return;
        }
        ((AbstractLayoutManager) lm).possiblyRegisterMarkersForTables(markers, isStarting, isFirst, isLast);
    }

    public boolean handlingFloat() {
        if (parentLayoutManager != null && parentLayoutManager instanceof AbstractLayoutManager) {
            return ((AbstractLayoutManager) parentLayoutManager).handlingFloat();
        }
        return false;
    }
}
