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

import java.awt.geom.Rectangle2D;

import org.apache.xmlgraphics.image.codec.tiff.TIFFImage;
import org.apache.xmlgraphics.java2d.Graphics2DImagePainter;

import org.apache.fop.afp.ioca.IDEStructureParameter;
import org.apache.fop.afp.ioca.ImageContent;
import org.apache.fop.afp.modca.AbstractDataObject;
import org.apache.fop.afp.modca.AbstractNamedAFPObject;
import org.apache.fop.afp.modca.Document;
import org.apache.fop.afp.modca.GraphicsObject;
import org.apache.fop.afp.modca.ImageObject;
import org.apache.fop.afp.modca.IncludeObject;
import org.apache.fop.afp.modca.ObjectContainer;
import org.apache.fop.afp.modca.Overlay;
import org.apache.fop.afp.modca.PageSegment;
import org.apache.fop.afp.modca.Registry;
import org.apache.fop.afp.modca.ResourceObject;
import org.apache.fop.afp.modca.triplets.MappingOptionTriplet;
import org.apache.fop.afp.modca.triplets.ObjectClassificationTriplet;

/**
 * Factory for high level data objects (Image/Graphics etc)
 */
public class AFPDataObjectFactory {

    private final Factory factory;

    /**
     * Main constructor
     *
     * @param factory an object factory
     */
    public AFPDataObjectFactory(Factory factory) {
        this.factory = factory;
    }

    /**
     * Creates and configures an ObjectContainer.
     *
     * @param dataObjectInfo the object container info
     * @return a newly created Object Container
     */
    public ObjectContainer createObjectContainer(AFPDataObjectInfo dataObjectInfo) {
        ObjectContainer objectContainer = factory.createObjectContainer();

        // set data object viewport (i.e. position, rotation, dimension, resolution)
        objectContainer.setViewport(dataObjectInfo);

        // set object classification
        Registry.ObjectType objectType = dataObjectInfo.getObjectType();
        AFPResourceInfo resourceInfo = dataObjectInfo.getResourceInfo();
        AFPResourceLevel resourceLevel = resourceInfo.getLevel();
        final boolean dataInContainer = true;
        final boolean containerHasOEG = resourceLevel.isInline();
        final boolean dataInOCD = true;
        objectContainer.setObjectClassification(
                ObjectClassificationTriplet.CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT,
                objectType, dataInContainer, containerHasOEG, dataInOCD);

        objectContainer.setData(dataObjectInfo.getData());
        return objectContainer;
    }

    /**
     * Creates and configures an IOCA Image Object.
     *
     * @param imageObjectInfo the image object info
     * @return a newly created IOCA Image Object
     */
    public ImageObject createImage(AFPImageObjectInfo imageObjectInfo) {
        // IOCA bitmap image
        ImageObject imageObj = factory.createImageObject();

        // set data object viewport (i.e. position, rotation, dimension, resolution)
        imageObj.setViewport(imageObjectInfo);

        if (imageObjectInfo.hasCompression()) {
            int compression = imageObjectInfo.getCompression();
            switch (compression) {
            case TIFFImage.COMP_FAX_G3_1D:
                imageObj.setEncoding(ImageContent.COMPID_G3_MH);
                break;
            case TIFFImage.COMP_FAX_G3_2D:
                imageObj.setEncoding(ImageContent.COMPID_G3_MR);
                break;
            case TIFFImage.COMP_FAX_G4_2D:
                imageObj.setEncoding(ImageContent.COMPID_G3_MMR);
                break;
            case ImageContent.COMPID_JPEG:
                imageObj.setEncoding((byte)compression);
                break;
            default:
                throw new IllegalStateException(
                        "Invalid compression scheme: " + compression);
            }
        }

        ImageContent content = imageObj.getImageSegment().getImageContent();
        int bitsPerPixel = imageObjectInfo.getBitsPerPixel();
        imageObj.setIDESize((byte) bitsPerPixel);
        IDEStructureParameter ideStruct;
        switch (bitsPerPixel) {
        case 1:
            //Skip IDE Structure Parameter
            break;
        case 4:
        case 8:
            //A grayscale image
            ideStruct = content.needIDEStructureParameter();
            ideStruct.setBitsPerComponent(new int[] {bitsPerPixel});
            ideStruct.setColorModel(IDEStructureParameter.COLOR_MODEL_YCBCR);
            break;
        case 24:
            ideStruct = content.needIDEStructureParameter();
            ideStruct.setDefaultRGBColorModel();
            break;
        case 32:
            ideStruct = content.needIDEStructureParameter();
            ideStruct.setDefaultCMYKColorModel();
            break;
        default:
            throw new IllegalArgumentException("Unsupported number of bits per pixel: "
                    + bitsPerPixel);
        }
        if (bitsPerPixel > 1 && imageObjectInfo.isSubtractive()) {
            ideStruct = content.needIDEStructureParameter();
            ideStruct.setSubtractive(imageObjectInfo.isSubtractive());
        }

        imageObj.setData(imageObjectInfo.getData());

        return imageObj;
    }

    /**
     * Creates and returns a new graphics object.
     *
     * @param graphicsObjectInfo the graphics object info
     * @return a new graphics object
     */
    public GraphicsObject createGraphic(AFPGraphicsObjectInfo graphicsObjectInfo) {
        // set newly created graphics object in g2d
        GraphicsObject graphicsObj = factory.createGraphicsObject();

        // set data object viewport (i.e. position, rotation, dimension, resolution)
        graphicsObj.setViewport(graphicsObjectInfo);

        AFPGraphics2D g2d = graphicsObjectInfo.getGraphics2D();
        g2d.setGraphicsObject(graphicsObj);

        //set color converter (i.e. an rgb to grayscale converter)
        graphicsObj.setColorConverter(g2d.getPaintingState().getColorConverter());

        // paint to graphics object
        Graphics2DImagePainter painter = graphicsObjectInfo.getPainter();
        Rectangle2D area = graphicsObjectInfo.getArea();
        g2d.scale(1, -1);
        g2d.translate(0, -area.getHeight());

        painter.paint(g2d, area);

        graphicsObj.setComplete(true);

        // return painted graphics object
        return graphicsObj;
    }

    /**
     * Creates and returns a new include object.
     *
     * @param includeName the include name
     * @param dataObjectInfo a data object info
     *
     * @return a new include object
     */
    public IncludeObject createInclude(String includeName, AFPDataObjectInfo dataObjectInfo) {
        IncludeObject includeObj = factory.createInclude(includeName);

        if (dataObjectInfo instanceof AFPImageObjectInfo) {
            // IOCA image object
            includeObj.setObjectType(IncludeObject.TYPE_IMAGE);
        } else if (dataObjectInfo instanceof AFPGraphicsObjectInfo) {
            // graphics object
            includeObj.setObjectType(IncludeObject.TYPE_GRAPHIC);
        } else {
            // object container
            includeObj.setObjectType(IncludeObject.TYPE_OTHER);

            // set mandatory object classification (type other)
            Registry.ObjectType objectType = dataObjectInfo.getObjectType();
            if (objectType != null) {
                // set object classification
                final boolean dataInContainer = true;
                final boolean containerHasOEG = false; // environment parameters set in include
                final boolean dataInOCD = true;
                includeObj.setObjectClassification(
                   // object scope not defined
                   ObjectClassificationTriplet.CLASS_TIME_VARIANT_PRESENTATION_OBJECT,
                   objectType, dataInContainer, containerHasOEG, dataInOCD);
            } else {
                throw new IllegalStateException(
                        "Failed to set Object Classification Triplet on Object Container.");
            }
        }

        AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo();

        int xOffset = objectAreaInfo.getX();
        int yOffset = objectAreaInfo.getY();
        includeObj.setObjectAreaOffset(xOffset, yOffset);

        int width = objectAreaInfo.getWidth();
        int height = objectAreaInfo.getHeight();
        includeObj.setObjectAreaSize(width, height);

        int rotation = objectAreaInfo.getRotation();
        includeObj.setObjectAreaOrientation(rotation);

        int widthRes = objectAreaInfo.getWidthRes();
        int heightRes = objectAreaInfo.getHeightRes();
        includeObj.setMeasurementUnits(widthRes, heightRes);

        includeObj.setMappingOption(MappingOptionTriplet.SCALE_TO_FIT);

        return includeObj;
    }

    /**
     * Creates a resource object wrapper for named includable data objects
     *
     * @param namedObj an named object
     * @param resourceInfo resource information
     * @param objectType the object type
     * @return a new resource object wrapper
     */
    public ResourceObject createResource(AbstractNamedAFPObject namedObj,
            AFPResourceInfo resourceInfo, Registry.ObjectType objectType) {
        ResourceObject resourceObj = null;
        String resourceName = resourceInfo.getName();
        if (resourceName != null) {
            resourceObj = factory.createResource(resourceName);
        } else {
            resourceObj = factory.createResource();
        }

        if (namedObj instanceof Document) {
            resourceObj.setType(ResourceObject.TYPE_DOCUMENT);
        } else if (namedObj instanceof PageSegment) {
            resourceObj.setType(ResourceObject.TYPE_PAGE_SEGMENT);
        } else if (namedObj instanceof Overlay) {
            resourceObj.setType(ResourceObject.TYPE_OVERLAY_OBJECT);
        } else if (namedObj instanceof AbstractDataObject) {
            AbstractDataObject dataObj = (AbstractDataObject)namedObj;
            if (namedObj instanceof ObjectContainer) {
                resourceObj.setType(ResourceObject.TYPE_OBJECT_CONTAINER);

                // set object classification
                final boolean dataInContainer = true;
                final boolean containerHasOEG = false; // must be included
                final boolean dataInOCD = true;
                // mandatory triplet for object container
                resourceObj.setObjectClassification(
                    ObjectClassificationTriplet.CLASS_TIME_INVARIANT_PAGINATED_PRESENTATION_OBJECT,
                    objectType, dataInContainer, containerHasOEG, dataInOCD);
            } else if (namedObj instanceof ImageObject) {
                // ioca image type
                resourceObj.setType(ResourceObject.TYPE_IMAGE);
            } else if (namedObj instanceof GraphicsObject) {
                resourceObj.setType(ResourceObject.TYPE_GRAPHIC);
            } else {
                throw new UnsupportedOperationException(
                        "Unsupported resource object for data object type " + dataObj);
            }
        } else {
            throw new UnsupportedOperationException(
              "Unsupported resource object type " + namedObj);
        }

        // set the resource information/classification on the data object
        resourceObj.setDataObject(namedObj);
        return resourceObj;
    }

}
