/*
 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
 */

package com.sun.rain.graphics;

import com.sun.glass.ui.Pixels;
import java.nio.*;

public class Image
{
    public enum Type { ARGB_PRE }
    
    static native void _initIDs();
    static
    {
        System.loadLibrary("rain");
        _initIDs();
    }
    
    static private ByteBuffer createBuffer(int size)
    {
        ByteBuffer buffer = ByteBuffer.allocateDirect(size);
        buffer.order(ByteOrder.nativeOrder());
        buffer.rewind();
        
        return buffer;
    }
    static private ByteBuffer createBuffer(final byte pixels[])
    {
        ByteBuffer buffer = createBuffer(pixels.length);

        for (int i=0; i<pixels.length; i++)
        {
            buffer.put(pixels[i]);
        }
        buffer.rewind();
        
        return buffer;
    }
    static private ByteBuffer createBuffer(final int pixels[])
    {
        ByteBuffer buffer = createBuffer(pixels.length*4);

        for (int i=0; i<pixels.length; i++)
        {
            buffer.putInt(pixels[i]);
        }
        buffer.rewind();

        return buffer;
    }
    static private ByteBuffer convertArgbToArgbPre(ByteBuffer pixels)
    {
        for (int i=0; i<pixels.capacity(); i+=4)
        {
            float af = (float)(pixels.get() & 0x000000ff)/255.0f;

            pixels.mark();
            float rf = af * (float)(pixels.get() & 0x000000ff);
            float gf = af * (float)(pixels.get() & 0x000000ff);
            float bf = af * (float)(pixels.get() & 0x000000ff);
            
            pixels.reset();
            pixels.put((byte)((int)rf & 0x000000ff));
            pixels.put((byte)((int)gf & 0x000000ff));
            pixels.put((byte)((int)bf & 0x000000ff));
        }
        
        pixels.rewind();
        
        return pixels;
    }
    
    private long ptr; // set by native code
    
    private int width, height;
    private ByteBuffer pixels;
    
    // pixels MUST be in ARGB or ARGB_PRE format (in host byte order)
    native private void _createImage(int width, int height, ByteBuffer pixels);
    public Image(int width, int height, boolean alphaPremultiplied)
    {
        this(width, height, (ByteBuffer)null, alphaPremultiplied);
    }
    public Image(final int width, final int height, final int pixels[], boolean alphaPremultiplied)
    {
        this(width, height, createBuffer(pixels), alphaPremultiplied);
    }
    public Image(final int width, final int height, final byte pixels[], boolean alphaPremultiplied)
    {
        this(width, height, createBuffer(pixels), alphaPremultiplied);
    }
    public Image(final Pixels pxls, boolean alphaPremultiplied)
    {
        this(pxls.getWidth(), pxls.getHeight(), pxls.asByteBuffer(), alphaPremultiplied);
    }
    public Image(final int width, final int height, final ByteBuffer pixels, boolean alphaPremultiplied)
    {
        this.ptr = 0L;
        this.width = width;
        this.height = height;
        this.pixels = pixels;
        
        if (this.pixels == null)
        {
            this.pixels = createBuffer(this.width*this.height*4);
        }
        
        if (alphaPremultiplied == false)
        {
            convertArgbToArgbPre(this.pixels);
        }
        
        this.pixels.rewind();
        _createImage(this.width, this.height, this.pixels);
    }
    
    public Type getType()
    {
        return Type.ARGB_PRE;
    }
    
    public int getWidth()
    {
        return this.width;
    }
    
    public int getHeight()
    {
        return this.height;
    }
    
    public ByteBuffer getPixels()
    {
        return this.pixels;
    }
    
    void dumpImage()
    {
        int p = 0;
        for (int y=0; y<getHeight(); y++)
        {
            for (int x=0; x<getWidth(); x++)
            {
                System.out.print("0x");
                
                for (int i=0; i<4; i++)
                {
                    int pixel = (this.pixels.get() & 0x000000ff);
                    if (pixel <= 0xf)
                    {
                        System.out.print("0");
                    }
                    System.out.print(Integer.toHexString(pixel));
                }

                System.out.print(", ");
                if ((p != 0) && (p%8 == 0))
                {
                    System.out.println();
                }
            }
        }
    }
}
