/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed 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.
 */

package com.android.ddmlib;

import java.nio.ByteBuffer;

/**
 * Data representing an image taken from a device frame buffer.
 */
public final class RawImage {
    public int version;
    public int bpp;
    public int size;
    public int width;
    public int height;
    public int red_offset;
    public int red_length;
    public int blue_offset;
    public int blue_length;
    public int green_offset;
    public int green_length;
    public int alpha_offset;
    public int alpha_length;

    public byte[] data;

    /**
     * Reads the header of a RawImage from a {@link ByteBuffer}.
     * <p/>The way the data is sent over adb is defined in system/core/adb/framebuffer_service.c
     * @param version the version of the protocol.
     * @param buf the buffer to read from.
     * @return true if success
     */
    public boolean readHeader(int version, ByteBuffer buf) {
        this.version = version;

        if (version == 16) {
            // compatibility mode with original protocol
            this.bpp = 16;

            // read actual values.
            this.size = buf.getInt();
            this.width = buf.getInt();
            this.height = buf.getInt();

            // create default values for the rest. Format is 565
            this.red_offset = 11;
            this.red_length = 5;
            this.green_offset = 5;
            this.green_length = 6;
            this.blue_offset = 0;
            this.blue_length = 5;
            this.alpha_offset = 0;
            this.alpha_length = 0;
        } else if (version == 1) {
            this.bpp = buf.getInt();
            this.size = buf.getInt();
            this.width = buf.getInt();
            this.height = buf.getInt();
            this.red_offset = buf.getInt();
            this.red_length = buf.getInt();
            this.blue_offset = buf.getInt();
            this.blue_length = buf.getInt();
            this.green_offset = buf.getInt();
            this.green_length = buf.getInt();
            this.alpha_offset = buf.getInt();
            this.alpha_length = buf.getInt();
        } else {
            // unsupported protocol!
            return false;
        }

        return true;
    }

    /**
     * Returns the mask value for the red color.
     * <p/>This value is compatible with org.eclipse.swt.graphics.PaletteData
     */
    public int getRedMask() {
        return getMask(red_length, red_offset);
    }

    /**
     * Returns the mask value for the green color.
     * <p/>This value is compatible with org.eclipse.swt.graphics.PaletteData
     */
    public int getGreenMask() {
        return getMask(green_length, green_offset);
    }

    /**
     * Returns the mask value for the blue color.
     * <p/>This value is compatible with org.eclipse.swt.graphics.PaletteData
     */
    public int getBlueMask() {
        return getMask(blue_length, blue_offset);
    }

    /**
     * Returns the size of the header for a specific version of the framebuffer adb protocol.
     * @param version the version of the protocol
     * @return the number of int that makes up the header.
     */
    public static int getHeaderSize(int version) {
        switch (version) {
            case 16: // compatibility mode
                return 3; // size, width, height
            case 1:
                return 12; // bpp, size, width, height, 4*(length, offset)
        }

        return 0;
    }

    /**
     * Returns a rotated version of the image
     * The image is rotated counter-clockwise.
     */
    public RawImage getRotated() {
        RawImage rotated = new RawImage();
        rotated.version = this.version;
        rotated.bpp = this.bpp;
        rotated.size = this.size;
        rotated.red_offset = this.red_offset;
        rotated.red_length = this.red_length;
        rotated.blue_offset = this.blue_offset;
        rotated.blue_length = this.blue_length;
        rotated.green_offset = this.green_offset;
        rotated.green_length = this.green_length;
        rotated.alpha_offset = this.alpha_offset;
        rotated.alpha_length = this.alpha_length;

        rotated.width = this.height;
        rotated.height = this.width;

        int count = this.data.length;
        rotated.data = new byte[count];

        int byteCount = this.bpp >> 3; // bpp is in bits, we want bytes to match our array
        final int w = this.width;
        final int h = this.height;
        for (int y = 0 ; y < h ; y++) {
            for (int x = 0 ; x < w ; x++) {
                System.arraycopy(
                        this.data, (y * w + x) * byteCount,
                        rotated.data, ((w-x-1) * h + y) * byteCount,
                        byteCount);
            }
        }

        return rotated;
    }

    /**
     * Returns an ARGB integer value for the pixel at <var>index</var> in {@link #data}.
     */
    public int getARGB(int index) {
        int value;
        int r, g, b, a;
        if (bpp == 16) {
            value = data[index] & 0x00FF;
            value |= (data[index+1] << 8) & 0x0FF00;
            // RGB565 to RGB888
            // Multiply by 255/31 to convert from 5 bits (31 max) to 8 bits (255)
            r = ((value >>> 11) & 0x1f) * 255/31;
            g = ((value >>> 5)  & 0x3f) * 255/63;
            b = ((value)        & 0x1f) * 255/31;
            a = 0xFF; // force alpha to opaque if there's no alpha value in the framebuffer.
        } else if (bpp == 32) {
            value = data[index] & 0x00FF;
            value |= (data[index+1] & 0x00FF) << 8;
            value |= (data[index+2] & 0x00FF) << 16;
            value |= (data[index+3] & 0x00FF) << 24;
            r = ((value >>> red_offset) & getMask(red_length)) << (8 - red_length);
            g = ((value >>> green_offset) & getMask(green_length)) << (8 - green_length);
            b = ((value >>> blue_offset) & getMask(blue_length)) << (8 - blue_length);
            a = ((value >>> alpha_offset) & getMask(alpha_length)) << (8 - alpha_length);
        } else {
            throw new UnsupportedOperationException("RawImage.getARGB(int) only works in 16 and 32 bit mode.");
        }

        return a << 24 | r << 16 | g << 8 | b;
    }

    /**
     * creates a mask value based on a length and offset.
     * <p/>This value is compatible with org.eclipse.swt.graphics.PaletteData
     */
    private int getMask(int length, int offset) {
        int res = getMask(length) << offset;

        // if the bpp is 32 bits then we need to invert it because the buffer is in little endian
        if (bpp == 32) {
            return Integer.reverseBytes(res);
        }

        return res;
    }

    /**
     * Creates a mask value based on a length.
     * @param length
     * @return
     */
    private static int getMask(int length) {
        return (1 << length) - 1;
    }
}
