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

import java.awt.Color;
import java.awt.Transparency;
import java.awt.image.ColorModel;
import java.awt.image.IndexColorModel;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import java.awt.image.BufferedImage;
import java.io.IOException;

import org.apache.xmlgraphics.image.GraphicsUtil;
import org.apache.xmlgraphics.image.codec.util.SeekableStream;
import org.apache.xmlgraphics.image.codec.util.MemoryCacheSeekableStream;
import org.apache.xmlgraphics.image.codec.util.FileCacheSeekableStream;
import org.apache.xmlgraphics.image.rendered.CachableRed;

import org.apache.commons.io.IOUtils;

/**
 * Abstract FopImage implementation which uses the internal codecs from XML Graphics Commons.
 * @see AbstractFopImage
 * @see FopImage
 */
public abstract class XmlGraphicsCommonsImage extends AbstractFopImage {

    private byte[] softMask = null;

    /**
     * The InputStream wrapped into a SeekableStream for decoding.
     */
    protected SeekableStream seekableInput = null;

    /**
     * The Batik representation of the image
     */
    protected CachableRed cr = null;
    
    /**
     * Constructs a new BatikImage instance.
     * @param imgReader basic metadata for the image
     */
    public XmlGraphicsCommonsImage(FopImage.ImageInfo imgReader) {
        super(imgReader);
    }

    /**
     * @see org.apache.fop.image.AbstractFopImage#loadDimensions()
     */
    protected boolean loadDimensions() {
        if (seekableInput == null && inputStream != null) {
            try { 
                seekableInput = new FileCacheSeekableStream(inputStream);
            } catch (IOException ioe) {
                seekableInput = new MemoryCacheSeekableStream(inputStream);
            }
            try {
                this.bitsPerPixel = 8;
                cr = decodeImage(seekableInput);
                this.height = cr.getHeight();
                this.width  = cr.getWidth();
                this.isTransparent = false;
                this.softMask = null;
                ColorModel cm = cr.getColorModel();

                this.height = cr.getHeight();
                this.width  = cr.getWidth();
                this.isTransparent = false;
                this.softMask = null;

                int transparencyType = cm.getTransparency();
                if (cm instanceof IndexColorModel)  {
                    if (transparencyType == Transparency.BITMASK) {
                        // Use 'transparent color'.
                        IndexColorModel icm = (IndexColorModel)cm;
                        int numColor = icm.getMapSize();
                        byte [] alpha = new byte[numColor];
                        icm.getAlphas(alpha);
                        for (int i = 0; i < numColor; i++) {
                            if ((alpha[i] & 0xFF) == 0) {
                                this.isTransparent = true;
                                int red = (icm.getRed  (i)) & 0xFF;
                                int grn = (icm.getGreen(i)) & 0xFF;
                                int blu = (icm.getBlue (i)) & 0xFF;
                                this.transparentColor = new Color(red, grn, blu);
                                break;
                            }
                        }
                    }
                } else {
                    cr = GraphicsUtil.convertTosRGB(cr);
                }

                // Get our current ColorModel
                cm = cr.getColorModel();
                if (this.colorSpace == null) {
                    this.colorSpace = cm.getColorSpace();
                }
            } catch (IOException ioe) {
                log.error("Error while loading image (Batik): " + ioe.getMessage(), ioe);
                IOUtils.closeQuietly(seekableInput);
                IOUtils.closeQuietly(inputStream);
                seekableInput = null;
                inputStream = null;
                return false;
            }
        }
        return this.height != -1;
    }

    /**
     * @see org.apache.fop.image.AbstractFopImage#loadBitmap()
     */
    protected boolean loadBitmap() {
        if (this.bitmaps == null) {
            loadImage();
        }

        return this.bitmaps != null;
    }

    /**
     * @see org.apache.fop.image.FopImage#hasSoftMask()
     */
    public boolean hasSoftMask() {
        if (this.bitmaps == null && this.raw == null) {
            loadImage();
        }

        return (this.softMask != null);
    }

    /**
     * @see org.apache.fop.image.FopImage#getSoftMask()
     */
    public byte[] getSoftMask() {
        if (this.bitmaps == null) {
            loadImage();
        }

        return this.softMask;
    }

    /**
     * Decodes the image from the stream.
     * @param stream the stream to read the image from
     * @return the decoded image
     * @throws IOException in case an I/O problem occurs
     */
    protected abstract CachableRed decodeImage(SeekableStream stream) throws IOException;
    
    /**
     * Loads the image from the InputStream.
     */
    protected void loadImage() {
        if (loadDimensions()) {
            try {
                if (cr == null) {
                    throw new IllegalStateException(
                            "Can't load the bitmaps data without the CachableRed instance");
                }
                
                // Get our current ColorModel
                ColorModel cm = cr.getColorModel();

                // It has an alpha channel so generate a soft mask.
                if (!this.isTransparent && cm.hasAlpha()) {
                    this.softMask = new byte[this.width * this.height];
                }

                this.bitmaps = new byte[this.width * this.height * 3];

                constructBitmaps(cr, this.bitmaps, this.softMask);
            } catch (Exception ex) {
                log.error("Error while loading image (Batik): " + ex.getMessage(), ex);
            } finally {
                // Make sure we clean up
                IOUtils.closeQuietly(seekableInput);
                IOUtils.closeQuietly(inputStream);
                seekableInput = null;
                inputStream = null;
                cr = null;
            }
        }
    }

    private static void constructBitmaps(RenderedImage red, byte[] bitmaps, byte[] softMask) {
        WritableRaster wr = (WritableRaster)red.getData();
        ColorModel cm = red.getColorModel();
        BufferedImage bi = new BufferedImage
            (cm, wr.createWritableTranslatedChild(0, 0), 
             cm.isAlphaPremultiplied(), null);
        int width = red.getWidth();
        int height = red.getHeight();
        int [] tmpMap = new int[width];
        int idx = 0;
        int sfIdx = 0;
        for (int y = 0; y < height; y++) {
            tmpMap = bi.getRGB(0, y, width, 1, tmpMap, 0, width);
            if (softMask != null) {
                for (int x = 0; x < width; x++) {
                    int pix = tmpMap[x];
                    softMask[sfIdx++] = (byte)(pix >>> 24);
                    bitmaps[idx++]    = (byte)((pix >>> 16) & 0xFF);
                    bitmaps[idx++]    = (byte)((pix >>> 8)  & 0xFF);
                    bitmaps[idx++]    = (byte)((pix)        & 0xFF);
                }
            } else {
                for (int x = 0; x < width; x++) {
                    int pix = tmpMap[x];
                    bitmaps[idx++] = (byte)((pix >> 16) & 0xFF);
                    bitmaps[idx++] = (byte)((pix >> 8)  & 0xFF);
                    bitmaps[idx++] = (byte)((pix)       & 0xFF);
                }
            }
        }
    }
    
}