/*
 * 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.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;
import java.util.List;
import java.util.Map;

import org.apache.fop.datatypes.FODimension;
import org.apache.fop.datatypes.LengthBase;
import org.apache.fop.datatypes.SimplePercentBaseContext;
import org.apache.fop.fo.pagination.Region;
import org.apache.fop.fo.pagination.RegionBody;
import org.apache.fop.fo.pagination.SimplePageMaster;
import org.apache.fop.fo.properties.CommonMarginBlock;
import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.traits.WritingModeTraitsGetter;

import static org.apache.fop.fo.Constants.EN_ERROR_IF_OVERFLOW;
import static org.apache.fop.fo.Constants.EN_HIDDEN;
import static org.apache.fop.fo.Constants.FO_REGION_AFTER;
import static org.apache.fop.fo.Constants.FO_REGION_BEFORE;
import static org.apache.fop.fo.Constants.FO_REGION_BODY;
import static org.apache.fop.fo.Constants.FO_REGION_END;
import static org.apache.fop.fo.Constants.FO_REGION_START;

/**
 * The page.
 * This holds the contents of the page. Each region is added.
 * The unresolved references area added so that if the page is
 * serialized then it will handle the resolving properly after
 * being reloaded.
 * This is serializable so it can be saved to cache to save
 * memory if there are forward references.
 * The page is cloneable so the page master can make copies of
 * the top level page and regions.
 */
public class Page extends AreaTreeObject implements Serializable {

    private static final long serialVersionUID = 6272157047421543866L;

    // contains before, start, body, end and after regions
    private RegionViewport regionBefore;
    private RegionViewport regionStart;
    private RegionViewport regionBody;
    private RegionViewport regionEnd;
    private RegionViewport regionAfter;

    // temporary map of unresolved objects used when serializing the page
    private Map<String, List<Resolvable>> unresolved;

    /** Set to true to make this page behave as if it were not empty. */
    private boolean fakeNonEmpty;

    /**
     *  Empty constructor
     */
    public Page() { }

    /**
     * Constructor
     * @param spm SimplePageMaster containing the dimensions for this
     *            page-reference-area
     */
    public Page(SimplePageMaster spm) {
        // Width and Height of the page view port
        FODimension pageViewPortDims = new FODimension(spm.getPageWidth().getValue()
                            ,  spm.getPageHeight().getValue());

        // Get absolute margin properties (top, left, bottom, right)
        CommonMarginBlock mProps = spm.getCommonMarginBlock();

        /*
         * Create the page reference area rectangle (0,0 is at top left
         * of the "page media" and y increases
         * when moving towards the bottom of the page.
         * The media rectangle itself is (0,0,pageWidth,pageHeight).
         */
        /* Special rules apply to resolving margins in the page context.
         * Contrary to normal margins in this case top and bottom margin
         * are resolved relative to the height. In the property subsystem
         * all margin properties are configured to using BLOCK_WIDTH.
         * That's why we 'cheat' here and setup a context for the height but
         * use the LengthBase.BLOCK_WIDTH.
         */
        SimplePercentBaseContext pageWidthContext
            = new SimplePercentBaseContext(null, LengthBase.CONTAINING_BLOCK_WIDTH
                                            , pageViewPortDims.ipd);
        SimplePercentBaseContext pageHeightContext
            = new SimplePercentBaseContext(null, LengthBase.CONTAINING_BLOCK_WIDTH
                                            , pageViewPortDims.bpd);

        Rectangle pageRefRect
            =  new Rectangle(mProps.marginLeft.getValue(pageWidthContext)
                            , mProps.marginTop.getValue(pageHeightContext)
                            , pageViewPortDims.ipd
                                - mProps.marginLeft.getValue(pageWidthContext)
                                - mProps.marginRight.getValue(pageWidthContext)
                            , pageViewPortDims.bpd
                                - mProps.marginTop.getValue(pageHeightContext)
                                - mProps.marginBottom.getValue(pageHeightContext));

        // Set up the CTM on the page reference area based on writing-mode
        // and reference-orientation
        FODimension reldims = new FODimension(0, 0);
        CTM pageCTM = CTM.getCTMandRelDims(spm.getReferenceOrientation(),
            spm.getWritingMode(), pageRefRect, reldims);

        // Create a RegionViewport/ reference area pair for each page region
        RegionReference rr;
        for (Region r : spm.getRegions().values()) {
            RegionViewport rvp = makeRegionViewport(r, reldims, pageCTM);
            if (r.getNameId() == FO_REGION_BODY) {
                rr = new BodyRegion((RegionBody) r, rvp);
            } else {
                rr = new RegionReference(r, rvp);
            }
            // set borders and padding traits
            // (a little extensions wrt what prescribed by the specs at 6.4.14)
            TraitSetter.addBorders(rr, r.getCommonBorderPaddingBackground(),
                    false, false, false, false, null);
            TraitSetter.addPadding(rr, r.getCommonBorderPaddingBackground(),
                    false, false, false, false, null);
            setRegionReferencePosition(rr, r, rvp.getViewArea());
            rvp.setRegionReference(rr);
            setRegionViewport(r.getNameId(), rvp);
        }
    }

    /**
     * Call this method to force this page to pretend not to be empty.
     */
    public void fakeNonEmpty() {
        this.fakeNonEmpty = true;
    }

    /**
     * Creates a RegionViewport Area object for this pagination Region.
     * @param r the region the viewport is to be created for
     * @param reldims relative dimensions
     * @param pageCTM page coordinate transformation matrix
     * @return the new region viewport
     */
    private static RegionViewport makeRegionViewport(Region r, FODimension reldims, CTM pageCTM) {
        Rectangle2D relRegionRect = r.getViewportRectangle(reldims);
        Rectangle2D absRegionRect = pageCTM.transform(relRegionRect);
        // Get the region viewport rectangle in absolute coords by
        // transforming it using the page CTM
        RegionViewport rv = new RegionViewport(absRegionRect);
        rv.setBPD((int)relRegionRect.getHeight());
        rv.setIPD((int)relRegionRect.getWidth());
        TraitSetter.addBackground(rv, r.getCommonBorderPaddingBackground(), null);
        rv.setClip(r.getOverflow() == EN_HIDDEN
                || r.getOverflow() == EN_ERROR_IF_OVERFLOW);
        return rv;
    }

    /**
     * Set the region reference position within the region viewport.
     * This sets the transform that is used to place the contents of
     * the region reference.
     *
     * @param rr the region reference area
     * @param r the region-xxx formatting object
     * @param absRegVPRect The region viewport rectangle in "absolute" coordinates
     * where x=distance from left, y=distance from bottom, width=right-left
     * height=top-bottom
     */
    private static void setRegionReferencePosition(RegionReference rr, Region r,
                                  Rectangle2D absRegVPRect) {
        FODimension reldims = new FODimension(0, 0);
        rr.setCTM(CTM.getCTMandRelDims(r.getReferenceOrientation(),
                r.getWritingMode(), absRegVPRect, reldims));
        rr.setIPD(reldims.ipd
                - rr.getBorderAndPaddingWidthStart()
                - rr.getBorderAndPaddingWidthEnd());
        rr.setBPD(reldims.bpd
                - rr.getBorderAndPaddingWidthBefore()
                - rr.getBorderAndPaddingWidthAfter());
    }

    /**
     * Set the region on this page.
     *
     * @param areaclass the area class of the region to set
     * @param port the region viewport to set
     */
    public void setRegionViewport(int areaclass, RegionViewport port) {
        if (areaclass == FO_REGION_BEFORE) {
            regionBefore = port;
        } else if (areaclass == FO_REGION_START) {
            regionStart = port;
        } else if (areaclass == FO_REGION_BODY) {
            regionBody = port;
        } else if (areaclass == FO_REGION_END) {
            regionEnd = port;
        } else if (areaclass == FO_REGION_AFTER) {
            regionAfter = port;
        }
    }

    /**
     * Get the region from this page.
     *
     * @param areaClass the region area class
     * @return the region viewport or null if none
     */
    public RegionViewport getRegionViewport(int areaClass) {
        switch (areaClass) {
        case FO_REGION_BEFORE:
            return regionBefore;
        case FO_REGION_START:
            return regionStart;
        case FO_REGION_BODY:
            return regionBody;
        case FO_REGION_END:
            return regionEnd;
        case FO_REGION_AFTER:
            return regionAfter;
        default:
            throw new IllegalArgumentException("No such area class with ID = " + areaClass);
        }
    }

    /**
     * Indicates whether any FOs have been added to the body region
     *
     * @return whether any FOs have been added to the body region
     */
    public boolean isEmpty() {
        if (fakeNonEmpty) {
            return false;
        } else if (regionBody == null) {
            return true;
        } else {
            return regionBody.getRegionReference().isEmpty();
        }
    }

    /** {@inheritDoc} */
    public Object clone() throws CloneNotSupportedException {
        Page p = (Page) super.clone();
        if (regionBefore != null) {
            p.regionBefore = (RegionViewport)regionBefore.clone();
        }
        if (regionStart != null) {
            p.regionStart = (RegionViewport)regionStart.clone();
        }
        if (regionBody != null) {
            p.regionBody = (RegionViewport)regionBody.clone();
        }
        if (regionEnd != null) {
            p.regionEnd = (RegionViewport)regionEnd.clone();
        }
        if (regionAfter != null) {
            p.regionAfter = (RegionViewport)regionAfter.clone();
        }

        return p;
    }

    /**
     * Set the unresolved references on this page for serializing.
     *
     * @param unres the Map of unresolved objects
     */
    public void setUnresolvedReferences(Map<String, List<Resolvable>> unres) {
        unresolved = unres;
    }

    /**
     * Get the map unresolved references from this page.
     * This should be called after deserializing to retrieve
     * the map of unresolved references that were serialized.
     *
     * @return the de-serialized HashMap of unresolved objects
     */
    public Map<String, List<Resolvable>> getUnresolvedReferences() {
        return unresolved;
    }

    /**
     * Sets the writing mode traits for the region viewports of
     * this page.
     * @param wmtg a WM traits getter
     */
    public void setWritingModeTraits(WritingModeTraitsGetter wmtg) {
        if (regionBefore != null) {
            regionBefore.setWritingModeTraits(wmtg);
        }
        if (regionStart != null) {
            regionStart.setWritingModeTraits(wmtg);
        }
        if (regionBody != null) {
            regionBody.setWritingModeTraits(wmtg);
        }
        if (regionEnd != null) {
            regionEnd.setWritingModeTraits(wmtg);
        }
        if (regionAfter != null) {
            regionAfter.setWritingModeTraits(wmtg);
        }
    }

}


