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

import java.awt.Color;
import java.awt.Dimension;
import java.awt.geom.AffineTransform;
import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.fop.afp.AFPDitheredRectanglePainter;
import org.apache.fop.afp.AFPPaintingState;
import org.apache.fop.afp.AFPRectanglePainter;
import org.apache.fop.afp.AFPResourceLevelDefaults;
import org.apache.fop.afp.AFPResourceManager;
import org.apache.fop.afp.AFPUnitConverter;
import org.apache.fop.afp.AbstractAFPPainter;
import org.apache.fop.afp.DataStream;
import org.apache.fop.afp.fonts.AFPFontCollection;
import org.apache.fop.afp.fonts.AFPPageFonts;
import org.apache.fop.afp.modca.ResourceObject;
import org.apache.fop.afp.util.AFPResourceAccessor;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.fonts.FontCollection;
import org.apache.fop.fonts.FontEventAdapter;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.render.afp.AFPRendererConfig.AFPRendererConfigParser;
import org.apache.fop.render.afp.extensions.AFPElementMapping;
import org.apache.fop.render.afp.extensions.AFPIncludeFormMap;
import org.apache.fop.render.afp.extensions.AFPInvokeMediumMap;
import org.apache.fop.render.afp.extensions.AFPPageOverlay;
import org.apache.fop.render.afp.extensions.AFPPageSegmentElement;
import org.apache.fop.render.afp.extensions.AFPPageSetup;
import org.apache.fop.render.afp.extensions.ExtensionPlacement;
import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler;
import org.apache.fop.render.intermediate.IFContext;
import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator;
import org.apache.fop.render.intermediate.IFException;
import org.apache.fop.render.intermediate.IFPainter;

/**
 * {@link org.apache.fop.render.intermediate.IFDocumentHandler} implementation that produces AFP
 * (MO:DCA).
 */
public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
            implements AFPCustomizable {

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

    /** the resource manager */
    private AFPResourceManager resourceManager;

    /** the painting state */
    private final AFPPaintingState paintingState;

    /** unit converter */
    private final AFPUnitConverter unitConv;

    /** the AFP datastream */
    private DataStream dataStream;

    /** the map of page segments */
    private Map<String, PageSegmentDescriptor> pageSegmentMap
        = new java.util.HashMap<String, PageSegmentDescriptor>();


    // Rounded corners are cached at the document level
    private Map<String, String> roundedCornerNameCache
            = new HashMap<String, String>();

    private int roundedCornerCount;

    private static enum Location {
        ELSEWHERE, IN_DOCUMENT_HEADER, FOLLOWING_PAGE_SEQUENCE, IN_PAGE_HEADER
    }

    private Location location = Location.ELSEWHERE;

    /** temporary holds extensions that have to be deferred until the end of the page-sequence */
    private List<AFPPageSetup> deferredPageSequenceExtensions
        = new java.util.LinkedList<AFPPageSetup>();

    /** the shading mode for filled rectangles */
    private AFPShadingMode shadingMode = AFPShadingMode.COLOR;

    /**
     * Default constructor.
     */
    public AFPDocumentHandler(IFContext context) {
        super(context);
        this.resourceManager = new AFPResourceManager(context.getUserAgent().getResourceResolver());
        this.paintingState = new AFPPaintingState();
        this.unitConv = paintingState.getUnitConverter();
    }

    /** {@inheritDoc} */
    public boolean supportsPagesOutOfOrder() {
        return false;
    }

    /** {@inheritDoc} */
    public String getMimeType() {
        return MimeConstants.MIME_AFP;
    }

    /** {@inheritDoc} */
    public IFDocumentHandlerConfigurator getConfigurator() {
        return new AFPRendererConfigurator(getUserAgent(), new AFPRendererConfigParser());
    }

    /** {@inheritDoc} */
    @Override
    public void setDefaultFontInfo(FontInfo fontInfo) {
        FontManager fontManager = getUserAgent().getFontManager();
        FontCollection[] fontCollections = new FontCollection[] {
            new AFPFontCollection(getUserAgent().getEventBroadcaster(), null)
        };

        FontInfo fi = (fontInfo != null ? fontInfo : new FontInfo());
        fi.setEventListener(new FontEventAdapter(getUserAgent().getEventBroadcaster()));
        fontManager.setup(fi, fontCollections);
        setFontInfo(fi);
    }

    AFPPaintingState getPaintingState() {
        return this.paintingState;
    }

    DataStream getDataStream() {
        return this.dataStream;
    }

    AFPResourceManager getResourceManager() {
        return this.resourceManager;
    }

    AbstractAFPPainter createRectanglePainter() {
        if (AFPShadingMode.DITHERED.equals(this.shadingMode)) {
            return new AFPDitheredRectanglePainter(
                    getPaintingState(), getDataStream(), getResourceManager());
        } else {
            return new AFPRectanglePainter(
                    getPaintingState(), getDataStream());
        }
    }

    /** {@inheritDoc} */
    @Override
    public void startDocument() throws IFException {
        super.startDocument();
        try {
            paintingState.setColor(Color.WHITE);

            this.dataStream = resourceManager.createDataStream(paintingState, outputStream);

            this.dataStream.startDocument();
        } catch (IOException e) {
            throw new IFException("I/O error in startDocument()", e);
        }
    }


    /** {@inheritDoc} */
    @Override
    public void startDocumentHeader() throws IFException {
        super.startDocumentHeader();
        this.location = Location.IN_DOCUMENT_HEADER;
    }

    /** {@inheritDoc} */
    @Override
    public void endDocumentHeader() throws IFException {
        super.endDocumentHeader();
        this.location = Location.ELSEWHERE;
    }

    /** {@inheritDoc} */
    @Override
    public void endDocument() throws IFException {
        try {
            this.dataStream.endDocument();
            this.dataStream = null;
            this.resourceManager.writeToStream();
            this.resourceManager = null;
        } catch (IOException ioe) {
            throw new IFException("I/O error in endDocument()", ioe);
        }
        super.endDocument();
    }

    /** {@inheritDoc} */
    public void startPageSequence(String id) throws IFException {
        try {
            if (!"false".equals(getContext().getForeignAttribute(AFPElementMapping.PAGE_GROUP))) {
                dataStream.startPageGroup();
            }
        } catch (IOException ioe) {
            throw new IFException("I/O error in startPageSequence()", ioe);
        }
        this.location = Location.FOLLOWING_PAGE_SEQUENCE;
    }

    /** {@inheritDoc} */
    public void endPageSequence() throws IFException {
        try {
            //Process deferred page-sequence-level extensions
            Iterator<AFPPageSetup> iter = this.deferredPageSequenceExtensions.iterator();
            while (iter.hasNext()) {
                AFPPageSetup aps = iter.next();
                iter.remove();
                if (AFPElementMapping.NO_OPERATION.equals(aps.getElementName())) {
                    handleNOP(aps);
                } else {
                    throw new UnsupportedOperationException("Don't know how to handle " + aps);
                }
            }

            //End page sequence
            dataStream.endPageGroup();
        } catch (IOException ioe) {
            throw new IFException("I/O error in endPageSequence()", ioe);
        }
        this.location = Location.ELSEWHERE;
    }

    /**
     * Returns the base AFP transform
     *
     * @return the base AFP transform
     */
    private AffineTransform getBaseTransform() {
        AffineTransform baseTransform = new AffineTransform();
        double scale = unitConv.mpt2units(1);
        baseTransform.scale(scale, scale);
        return baseTransform;
    }

    /** {@inheritDoc} */
    public void startPage(int index, String name, String pageMasterName, Dimension size)
                throws IFException {
        this.location = Location.ELSEWHERE;
        paintingState.clear();

        AffineTransform baseTransform = getBaseTransform();
        paintingState.concatenate(baseTransform);

        int pageWidth = Math.round(unitConv.mpt2units(size.width));
        paintingState.setPageWidth(pageWidth);

        int pageHeight = Math.round(unitConv.mpt2units(size.height));
        paintingState.setPageHeight(pageHeight);

        int pageRotation = paintingState.getPageRotation();
        int resolution = paintingState.getResolution();

        dataStream.startPage(pageWidth, pageHeight, pageRotation,
                resolution, resolution);
    }

    /** {@inheritDoc} */
    @Override
    public void startPageHeader() throws IFException {
        super.startPageHeader();
        this.location = Location.IN_PAGE_HEADER;
    }

    /** {@inheritDoc} */
    @Override
    public void endPageHeader() throws IFException {
        this.location = Location.ELSEWHERE;
        super.endPageHeader();
    }

    /** {@inheritDoc} */
    public IFPainter startPageContent() throws IFException {
        return new AFPPainter(this);
    }

    /** {@inheritDoc} */
    public void endPageContent() throws IFException {
    }

    /** {@inheritDoc} */
    public void endPage() throws IFException {
        try {
            AFPPageFonts pageFonts = paintingState.getPageFonts();
            if (pageFonts != null && !pageFonts.isEmpty()) {
                dataStream.addFontsToCurrentPage(pageFonts);
            }

            dataStream.endPage();
        } catch (IOException ioe) {
            throw new IFException("I/O error in endPage()", ioe);
        }
    }

    /** {@inheritDoc} */
    public void handleExtensionObject(Object extension) throws IFException {
        if (extension instanceof AFPPageSetup) {
            AFPPageSetup aps = (AFPPageSetup)extension;
            String element = aps.getElementName();
            if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(element)) {
                switch (this.location) {
                case FOLLOWING_PAGE_SEQUENCE:
                case IN_PAGE_HEADER:
                    String name = aps.getName();
                    String value = aps.getValue();
                    int encoding = aps.getEncoding();
                    dataStream.createTagLogicalElement(name, value, encoding);
                    break;
                default:
                    throw new IFException(
                        "TLE extension must be in the page header or between page-sequence"
                            + " and the first page: " + aps, null);
                }
            } else if (AFPElementMapping.NO_OPERATION.equals(element)) {
                switch (this.location) {
                case FOLLOWING_PAGE_SEQUENCE:
                    if (aps.getPlacement() == ExtensionPlacement.BEFORE_END) {
                        this.deferredPageSequenceExtensions.add(aps);
                        break;
                    }
                case IN_DOCUMENT_HEADER:
                case IN_PAGE_HEADER:
                    handleNOP(aps);
                    break;
                default:
                    throw new IFException(
                            "NOP extension must be in the document header, the page header"
                                + " or between page-sequence"
                                + " and the first page: " + aps, null);
                }
            } else {
                if (this.location != Location.IN_PAGE_HEADER) {
                    throw new IFException(
                        "AFP page setup extension encountered outside the page header: " + aps,
                        null);
                }
                if (AFPElementMapping.INCLUDE_PAGE_SEGMENT.equals(element)) {
                    AFPPageSegmentElement.AFPPageSegmentSetup apse
                        = (AFPPageSegmentElement.AFPPageSegmentSetup)aps;
                    String name = apse.getName();
                    String source = apse.getValue();
                    String uri = apse.getResourceSrc();
                    pageSegmentMap.put(source, new PageSegmentDescriptor(name, uri));
                }
            }
        } else if (extension instanceof AFPPageOverlay) {
            AFPPageOverlay ipo = (AFPPageOverlay)extension;
            if (this.location != Location.IN_PAGE_HEADER) {
                    throw new IFException(
                        "AFP page overlay extension encountered outside the page header: " + ipo,
                        null);
            }
            String overlay = ipo.getName();
            if (overlay != null) {
                dataStream.createIncludePageOverlay(overlay, ipo.getX(), ipo.getY());
            }
        } else if (extension instanceof AFPInvokeMediumMap) {
            if (this.location != Location.FOLLOWING_PAGE_SEQUENCE
                    && this.location != Location.IN_PAGE_HEADER) {

                throw new IFException(
                    "AFP IMM extension must be between page-sequence"
                    + " and the first page or child of page-header: "
                    + extension, null);
            }
            AFPInvokeMediumMap imm = (AFPInvokeMediumMap)extension;
            String mediumMap = imm.getName();
            if (mediumMap != null) {
                dataStream.createInvokeMediumMap(mediumMap);
            }
        } else if (extension instanceof AFPIncludeFormMap) {
            AFPIncludeFormMap formMap = (AFPIncludeFormMap)extension;
            AFPResourceAccessor accessor = new AFPResourceAccessor(
                    getUserAgent().getResourceResolver());
            try {
                getResourceManager().createIncludedResource(formMap.getName(),
                        formMap.getSrc(), accessor,
                        ResourceObject.TYPE_FORMDEF, false, null);
            } catch (IOException ioe) {
                throw new IFException(
                        "I/O error while embedding form map resource: " + formMap.getName(), ioe);
            }
        }
    }

    /**
     * Corner images can be reused by storing at the document level in the AFP
     * The cache is used to map cahced images to caller generated descriptions of the corner
     * @param cornerKey caller's identifier for the corner
     * @return document id of the corner image
     */
    public String cacheRoundedCorner(String cornerKey) {

        // Make a unique id
        StringBuffer idBuilder = new StringBuffer("RC");

        String tmp = Integer.toHexString(roundedCornerCount).toUpperCase(Locale.ENGLISH);
        if (tmp.length() > 6) {
            //Will never happen
            //log.error("Rounded corners cache capacity exceeded");
            //We should get a visual clue
            roundedCornerCount = 0;
            tmp = "000000";
        } else if (tmp.length() < 6) {
            for (int i = 0; i < 6 - tmp.length(); i++) {
                idBuilder.append("0");
            }
            idBuilder.append(tmp);
        }

       roundedCornerCount++;

       String id =  idBuilder.toString();

       //cache the corner id
       roundedCornerNameCache.put(cornerKey, id);
       return id;
    }
    /**
     * This method returns the an id that identifies a cached corner or null if non existent
     * @param cornerKey caller's identifier for the corner
     * @return document id of the corner image
     */
    public String getCachedRoundedCorner(String cornerKey) {
        return roundedCornerNameCache.get(cornerKey);
    }


    private void handleNOP(AFPPageSetup nop) {
        String content = nop.getContent();
        if (content != null) {
            dataStream.createNoOperation(content);
        }
    }

    // ---=== AFPCustomizable ===---

    /** {@inheritDoc} */
    public void setBitsPerPixel(int bitsPerPixel) {
        paintingState.setBitsPerPixel(bitsPerPixel);
    }

    /** {@inheritDoc} */
    public void setColorImages(boolean colorImages) {
        paintingState.setColorImages(colorImages);
    }

    /** {@inheritDoc} */
    public void setNativeImagesSupported(boolean nativeImages) {
        paintingState.setNativeImagesSupported(nativeImages);
    }

    /** {@inheritDoc} */
    public void setCMYKImagesSupported(boolean value) {
        paintingState.setCMYKImagesSupported(value);
    }

    /** {@inheritDoc} */
    public void setDitheringQuality(float quality) {
        this.paintingState.setDitheringQuality(quality);
    }

    /** {@inheritDoc} */
    public void setBitmapEncodingQuality(float quality) {
        this.paintingState.setBitmapEncodingQuality(quality);
    }

    /** {@inheritDoc} */
    public void setShadingMode(AFPShadingMode shadingMode) {
        this.shadingMode = shadingMode;
    }

    /** {@inheritDoc} */
    public void setResolution(int resolution) {
        paintingState.setResolution(resolution);
    }

    /** {@inheritDoc} */
    public void setLineWidthCorrection(float correction) {
        paintingState.setLineWidthCorrection(correction);
    }

    /** {@inheritDoc} */
    public int getResolution() {
        return paintingState.getResolution();
    }

    /** {@inheritDoc} */
    public void setGOCAEnabled(boolean enabled) {
        this.paintingState.setGOCAEnabled(enabled);
    }

    /** {@inheritDoc} */
    public boolean isGOCAEnabled() {
        return this.paintingState.isGOCAEnabled();
    }

    /** {@inheritDoc} */
    public void setStrokeGOCAText(boolean stroke) {
        this.paintingState.setStrokeGOCAText(stroke);
    }

    /** {@inheritDoc} */
    public boolean isStrokeGOCAText() {
        return this.paintingState.isStrokeGOCAText();
    }

    /** {@inheritDoc} */
    public void setWrapPSeg(boolean pSeg) {
        paintingState.setWrapPSeg(pSeg);
    }

    public void setWrapGocaPSeg(boolean pSeg) {
        paintingState.setWrapGocaPSeg(pSeg);
    }

    /** {@inheritDoc} */
    public void setFS45(boolean fs45) {
        paintingState.setFS45(fs45);
    }

    /** {@inheritDoc} */
    public boolean getWrapPSeg() {
        return  paintingState.getWrapPSeg();
    }

    /** {@inheritDoc} */
    public boolean getFS45() {
        return  paintingState.getFS45();
    }

    public void setDefaultResourceGroupUri(URI uri) {
        resourceManager.setDefaultResourceGroupUri(uri);
    }

    /** {@inheritDoc} */
    public void setResourceLevelDefaults(AFPResourceLevelDefaults defaults) {
        resourceManager.setResourceLevelDefaults(defaults);
    }

    /**
     * Returns the page segment descriptor for a given URI if it actually represents a page segment.
     * Otherwise, it just returns null.
     * @param uri the URI that identifies the page segment
     * @return the page segment descriptor or null if there's no page segment for the given URI
     */
    PageSegmentDescriptor getPageSegmentNameFor(String uri) {
        return pageSegmentMap.get(uri);
    }

    /** {@inheritDoc} */
    public void canEmbedJpeg(boolean canEmbed) {
        paintingState.setCanEmbedJpeg(canEmbed);
    }

}
