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

package org.apache.commons.imaging.formats.ico;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.ImageWriteException;
import org.apache.commons.imaging.Sanselan;
import org.apache.commons.imaging.common.BinaryOutputStream;
import org.apache.commons.imaging.util.Debug;
import org.apache.commons.imaging.util.IoUtils;

public class IcoRoundtripTest extends IcoBaseTest
{
    // 16x16 test image
    private static final int[][] image = {
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,1,0,0,0,0,0,1,1,0,0,0,0},
        {0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,0},
        {0,0,1,0,1,0,0,0,1,0,0,0,0,1,0,0},
        {0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0},
        {0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0},
        {0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0},
        {0,0,0,0,1,0,0,0,1,0,1,1,1,0,0,0},
        {0,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0},
        {0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0},
        {0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0},
        {0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0},
        {0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
    };

    private Map generatorMap = new HashMap();

    public IcoRoundtripTest()
    {
        generatorMap.put(new Integer(1), new GeneratorFor1BitBitmaps());
        generatorMap.put(new Integer(4), new GeneratorFor4BitBitmaps());
        generatorMap.put(new Integer(8), new GeneratorFor8BitBitmaps());
        generatorMap.put(new Integer(16), new GeneratorFor16BitBitmaps());
        generatorMap.put(new Integer(24), new GeneratorFor24BitBitmaps());
        generatorMap.put(new Integer(32), new GeneratorFor32BitBitmaps());
    }

    private static interface BitmapGenerator
    {
        byte[] generateBitmap(int foreground, int background, int paletteSize)
                throws IOException, ImageWriteException;
    }

    private class GeneratorFor1BitBitmaps implements BitmapGenerator
    {
        public byte[] generateBitmap(int foreground, int background, int paletteSize)
                throws IOException, ImageWriteException
        {
            ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
            BinaryOutputStream bos = new BinaryOutputStream(byteArrayStream,
                    BinaryOutputStream.BYTE_ORDER_LITTLE_ENDIAN);
            // Palette
            bos.write3Bytes(background);
            bos.write(0);
            bos.write3Bytes(foreground);
            bos.write(0);
            for (int i = 2; i < paletteSize; i++)
                bos.write4Bytes(0);
            // Image
            for (int y = 15; y >= 0; y--)
            {
                for (int x = 0; x < 16; x += 8)
                {
                    bos.write(
                        ((0x1 & image[y][x]) << 7) |
                        ((0x1 & image[y][x+1]) << 6) |
                        ((0x1 & image[y][x+2]) << 5) |
                        ((0x1 & image[y][x+3]) << 4) |
                        ((0x1 & image[y][x+4]) << 3) |
                        ((0x1 & image[y][x+5]) << 2) |
                        ((0x1 & image[y][x+6]) << 1) |
                        ((0x1 & image[y][x+7]) << 0));
                }
                // Pad to multiple of 32 bytes
                bos.write(0);
                bos.write(0);
            }
            // Mask
            for (int y = image.length - 1; y >= 0; y--)
            {
                bos.write(0);
                bos.write(0);
                // Pad to 4 bytes:
                bos.write(0);
                bos.write(0);
            }
            bos.flush();
            return byteArrayStream.toByteArray();
        }
    }

    private class GeneratorFor4BitBitmaps implements BitmapGenerator
    {
        public byte[] generateBitmap(int foreground, int background, int paletteSize)
                throws IOException, ImageWriteException
        {
            ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
            BinaryOutputStream bos = new BinaryOutputStream(byteArrayStream,
                    BinaryOutputStream.BYTE_ORDER_LITTLE_ENDIAN);
            // Palette
            bos.write3Bytes(background);
            bos.write(0);
            bos.write3Bytes(foreground);
            bos.write(0);
            for (int i = 2; i < paletteSize; i++)
                bos.write4Bytes(0);
            // Image
            for (int y = 15; y >= 0; y--)
            {
                for (int x = 0; x < 16; x += 2)
                {
                    bos.write(((0xf & image[y][x]) << 4) |
                        (0xf & image[y][x+1]));
                }
            }
            // Mask
            for (int y = image.length - 1; y >= 0; y--)
            {
                bos.write(0);
                bos.write(0);
                // Pad to 4 bytes:
                bos.write(0);
                bos.write(0);
            }
            bos.flush();
            return byteArrayStream.toByteArray();
        }
    }

    private class GeneratorFor8BitBitmaps implements BitmapGenerator
    {
        public byte[] generateBitmap(int foreground, int background, int paletteSize)
                throws IOException, ImageWriteException
        {
            ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
            BinaryOutputStream bos = new BinaryOutputStream(byteArrayStream,
                    BinaryOutputStream.BYTE_ORDER_LITTLE_ENDIAN);
            // Palette
            bos.write3Bytes(background);
            bos.write(0);
            bos.write3Bytes(foreground);
            bos.write(0);
            for (int i = 2; i < paletteSize; i++)
                bos.write4Bytes(0);
            // Image
            for (int y = 15; y >= 0; y--)
            {
                for (int x = 0; x < 16; x++)
                {
                    bos.write(image[y][x]);
                }
            }
            // Mask
            for (int y = image.length - 1; y >= 0; y--)
            {
                bos.write(0);
                bos.write(0);
                // Pad to 4 bytes:
                bos.write(0);
                bos.write(0);
            }
            bos.flush();
            return byteArrayStream.toByteArray();
        }
    }

    private class GeneratorFor16BitBitmaps implements BitmapGenerator
    {
        public byte[] generateBitmap(int foreground, int background, int paletteSize)
                throws IOException, ImageWriteException
        {
            ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
            BinaryOutputStream bos = new BinaryOutputStream(byteArrayStream,
                    BinaryOutputStream.BYTE_ORDER_LITTLE_ENDIAN);
            // Palette
            for (int i = 0; i < paletteSize; i++)
                bos.write4Bytes(0);
            // Image
            for (int y = 15; y >= 0; y--)
            {
                for (int x = 0; x < 16; x++)
                {
                    if (image[y][x] == 1)
                        bos.write2Bytes((0x1f & (foreground >> 3)) |
                                ((0x1f & (foreground >> 11)) << 5) |
                                ((0x1f & (foreground >> 19)) << 10));
                    else
                        bos.write2Bytes((0x1f & (background >> 3)) |
                                ((0x1f & (background >> 11)) << 5) |
                                ((0x1f & (background >> 19)) << 10));
                }
            }
            // Mask
            for (int y = image.length - 1; y >= 0; y--)
            {
                bos.write(0);
                bos.write(0);
                // Pad to 4 bytes:
                bos.write(0);
                bos.write(0);
            }
            bos.flush();
            return byteArrayStream.toByteArray();
        }
    }

    private class GeneratorFor24BitBitmaps implements BitmapGenerator
    {
        public byte[] generateBitmap(int foreground, int background, int paletteSize)
                throws IOException, ImageWriteException
        {
            ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
            BinaryOutputStream bos = new BinaryOutputStream(byteArrayStream,
                    BinaryOutputStream.BYTE_ORDER_LITTLE_ENDIAN);
            // Palette
            for (int i = 0; i < paletteSize; i++)
                bos.write4Bytes(0);
            // Image
            for (int y = 15; y >= 0; y--)
            {
                for (int x = 0; x < 16; x++)
                {
                    if (image[y][x] == 1)
                        bos.write3Bytes(0xffffff & foreground);
                    else
                        bos.write3Bytes(0xffffff & background);
                }
            }
            // Mask
            for (int y = image.length - 1; y >= 0; y--)
            {
                bos.write(0);
                bos.write(0);
                // Pad to 4 bytes:
                bos.write(0);
                bos.write(0);
            }
            bos.flush();
            return byteArrayStream.toByteArray();
        }
    }

    private class GeneratorFor32BitBitmaps implements BitmapGenerator
    {
        public byte[] generateBitmap(int foreground, int background, int paletteSize)
                throws IOException, ImageWriteException
        {
            return generate32bitRGBABitmap(foreground, background, paletteSize, true);
        }

        public byte[] generate32bitRGBABitmap(int foreground, int background,
                int paletteSize, boolean writeMask) throws IOException
        {
            ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
            BinaryOutputStream bos = new BinaryOutputStream(byteArrayStream,
                    BinaryOutputStream.BYTE_ORDER_LITTLE_ENDIAN);
            // Palette
            for (int i = 0; i < paletteSize; i++)
                bos.write4Bytes(0);
            // Image
            for (int y = 15; y >= 0; y--)
            {
                for (int x = 0; x < 16; x++)
                {
                    if (image[y][x] == 1)
                        bos.write4Bytes(foreground);
                    else
                        bos.write4Bytes(background);
                }
            }
            // Mask
            if (writeMask)
            {
                for (int y = image.length - 1; y >= 0; y--)
                {
                    bos.write(0);
                    bos.write(0);
                    // Pad to 4 bytes:
                    bos.write(0);
                    bos.write(0);
                }
            }
            bos.flush();
            return byteArrayStream.toByteArray();
        }
    }

    private void writeICONDIR(BinaryOutputStream bos, int reserved, int type, int count)
            throws IOException
    {
        bos.write2Bytes(reserved);
        bos.write2Bytes(type);
        bos.write2Bytes(count);
    }

    private void writeICONDIRENTRY(BinaryOutputStream bos, int width, int height,
            int colorCount, int reserved, int planes, int bitCount, int bytesInRes)
            throws IOException
    {
        bos.write(width);
        bos.write(height);
        bos.write(colorCount);
        bos.write(reserved);
        bos.write2Bytes(planes);
        bos.write2Bytes(bitCount);
        bos.write4Bytes(bytesInRes);
        bos.write4Bytes(22); // image comes immediately after this
    }

    private void writeBITMAPINFOHEADER(BinaryOutputStream bos, int width, int height,
            int colorPlanes, int bitCount, int compression, int colorsUsed,
            int colorsImportant) throws IOException
    {
        // BITMAPINFOHEADER
        bos.write4Bytes(40); // biSize, always 40 for BITMAPINFOHEADER
        bos.write4Bytes(width); // biWidth
        bos.write4Bytes(height); // biHeight
        bos.write2Bytes(colorPlanes); // biPlanes
        bos.write2Bytes(bitCount); // bitCount
        bos.write4Bytes(compression); // biCompression
        bos.write4Bytes(0); // biSizeImage, can be 0 for uncompressed
        bos.write4Bytes(0); // X pixels per metre
        bos.write4Bytes(0); // Y pixels per metre
        bos.write4Bytes(colorsUsed); // colors used, ignored
        bos.write4Bytes(colorsImportant); // colors important
    }

    public void testNormalIcons() throws Exception
    {
        final int foreground = 0xFFF000E0;
        final int background = 0xFF102030;
        for (Iterator it = generatorMap.entrySet().iterator(); it.hasNext(); )
        {
            Map.Entry entry = (Map.Entry) it.next();
            int bitDepth = ((Integer)entry.getKey()).intValue();
            BitmapGenerator bitmapGenerator = (BitmapGenerator) entry.getValue();

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            BinaryOutputStream bos = new BinaryOutputStream(baos,
                    BinaryOutputStream.BYTE_ORDER_LITTLE_ENDIAN);
            byte[] bitmap = bitmapGenerator.generateBitmap(foreground, background,
                    (bitDepth <= 8) ? (1 << bitDepth) : 0);
            writeICONDIR(bos, 0, 1, 1);
            writeICONDIRENTRY(bos, 16, 16, 0, 0, 1, bitDepth, 40 + bitmap.length);
            writeBITMAPINFOHEADER(bos, 16, 2*16, 1, bitDepth, 0, 0, 0);
            bos.write(bitmap);
            bos.flush();
            writeAndReadImageData("16x16x" + bitDepth, baos.toByteArray(), foreground, background);
        }
    }

    public void testBadICONDIRENTRYIcons() throws Exception
    {
        final int foreground = 0xFFF000E0;
        final int background = 0xFF102030;
        // Windows ignores the ICONDIRENTRY values when parsing the ICO file.
        for (Iterator it = generatorMap.entrySet().iterator(); it.hasNext(); )
        {
            Map.Entry entry = (Map.Entry) it.next();
            int bitDepth = ((Integer)entry.getKey()).intValue();
            BitmapGenerator bitmapGenerator = (BitmapGenerator) entry.getValue();

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            BinaryOutputStream bos = new BinaryOutputStream(baos,
                    BinaryOutputStream.BYTE_ORDER_LITTLE_ENDIAN);
            byte[] bitmap = bitmapGenerator.generateBitmap(foreground, background,
                    (bitDepth <= 8) ? (1 << bitDepth) : 0);
            writeICONDIR(bos, 0, 1, 1);
            writeICONDIRENTRY(bos, 3 /* width, should be 16 */,
                    4 /* height, should be 16 */,
                    7 /* colorCount, should be 2 or 0 */,
                    20 /* reserved, should be 0 */,
                    11 /* planes, should be 1 or 0 */,
                    19 /* bitCount, should be bitDepth */,
                    40 + bitmap.length);
            writeBITMAPINFOHEADER(bos, 16, 2*16, 1, bitDepth, 0, 0, 0);
            bos.write(bitmap);
            bos.flush();
            writeAndReadImageData("16x16x" + bitDepth + "-corrupt-icondirentry",
                    baos.toByteArray(), foreground, background);
        }
    }

    public void testColorsUsed() throws Exception
    {
        final int foreground = 0xFFF000E0;
        final int background = 0xFF102030;
        for (Iterator it = generatorMap.entrySet().iterator(); it.hasNext(); )
        {
            Map.Entry entry = (Map.Entry) it.next();
            int bitDepth = ((Integer)entry.getKey()).intValue();
            BitmapGenerator bitmapGenerator = (BitmapGenerator) entry.getValue();

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            BinaryOutputStream bos = new BinaryOutputStream(baos,
                    BinaryOutputStream.BYTE_ORDER_LITTLE_ENDIAN);
            byte[] bitmap = bitmapGenerator.generateBitmap(foreground, background, 2);
            writeICONDIR(bos, 0, 1, 1);
            writeICONDIRENTRY(bos, 3, 4, 7, 20, 11, 19, 40 + bitmap.length);
            writeBITMAPINFOHEADER(bos, 16, 2*16, 1, bitDepth, 0, 2, 0);
            bos.write(bitmap);
            bos.flush();
            writeAndReadImageData("16x16x" + bitDepth + "-custom-palette",
                    baos.toByteArray(), foreground, background);
        }
    }

    public void testZeroColorPlanes() throws Exception
    {
        final int foreground = 0xFFF000E0;
        final int background = 0xFF102030;
        for (Iterator it = generatorMap.entrySet().iterator(); it.hasNext(); )
        {
            Map.Entry entry = (Map.Entry) it.next();
            int bitDepth = ((Integer)entry.getKey()).intValue();
            BitmapGenerator bitmapGenerator = (BitmapGenerator) entry.getValue();

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            BinaryOutputStream bos = new BinaryOutputStream(baos,
                    BinaryOutputStream.BYTE_ORDER_LITTLE_ENDIAN);
            byte[] bitmap = bitmapGenerator.generateBitmap(foreground, background,
                    (bitDepth <= 8) ? (1 << bitDepth) : 0);
            writeICONDIR(bos, 0, 1, 1);
            writeICONDIRENTRY(bos, 16, 16, 0, 0, 1, bitDepth, 40 + bitmap.length);
            writeBITMAPINFOHEADER(bos, 16, 2*16, 0 /* should be 1 */, bitDepth, 0, 0, 0);
            bos.write(bitmap);
            bos.flush();

            boolean threw = false;
            try
            {
                writeAndReadImageData("16x16x" + bitDepth + "-zero-colorPlanes",
                        baos.toByteArray(), foreground, background);
            }
            catch (ImageReadException imageReadException)
            {
                threw = true;
            }
            assertTrue(threw);
        }
    }

    public void testBitfieldCompression() throws Exception
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        BinaryOutputStream bos = new BinaryOutputStream(baos,
                BinaryOutputStream.BYTE_ORDER_LITTLE_ENDIAN);
        byte[] bitmap = new GeneratorFor32BitBitmaps().generate32bitRGBABitmap(
                0xFFFF0000, 0xFFFFFFFF, 0, true);
        writeICONDIR(bos, 0, 1, 1);
        writeICONDIRENTRY(bos, 16, 16, 0, 0, 1, 32, 40 + bitmap.length);
        writeBITMAPINFOHEADER(bos, 16, 2*16, 1, 32, 3 /* BI_BITFIELDS */, 0, 0);
        bos.write4Bytes(0x000000FF); // red mask
        bos.write4Bytes(0x0000FF00); // green mask
        bos.write4Bytes(0x00FF0000); // blue mask
        bos.write(bitmap);
        bos.flush();
        writeAndReadImageData("16x16x32-bitfield-compressed", baos.toByteArray(),
                0xFF0000FF, 0xFFFFFFFF);
    }

    public void test32bitMask() throws Exception
    {
        final int foreground = 0xFFF000E0;
        final int background = 0xFF102030;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        BinaryOutputStream bos = new BinaryOutputStream(baos,
                BinaryOutputStream.BYTE_ORDER_LITTLE_ENDIAN);
        // For 32 bit RGBA, the AND mask can be missing:
        byte[] bitmap = new GeneratorFor32BitBitmaps().generate32bitRGBABitmap(
                foreground, background, 0, false);
        writeICONDIR(bos, 0, 1, 1);
        writeICONDIRENTRY(bos, 16, 16, 0, 0, 1, 32, 40 + bitmap.length);
        writeBITMAPINFOHEADER(bos, 16, 2*16, 1, 32, 0, 0, 0);
        bos.write(bitmap);
        bos.flush();
        writeAndReadImageData("16x16x32-no-mask", baos.toByteArray(), foreground, background);
    }

    public void testAlphaVersusANDMask() throws Exception
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        BinaryOutputStream bos = new BinaryOutputStream(baos,
                BinaryOutputStream.BYTE_ORDER_LITTLE_ENDIAN);
        byte[] bitmap = new GeneratorFor32BitBitmaps().generate32bitRGBABitmap(
                0xFF000000, 0x00000000, 0, true);
        writeICONDIR(bos, 0, 1, 1);
        writeICONDIRENTRY(bos, 16, 16, 0, 0, 1, 32, 40 + bitmap.length);
        writeBITMAPINFOHEADER(bos, 16, 2*16, 1, 32, 0, 0, 0);
        bos.write(bitmap);
        bos.flush();
        // The AND mask is fully opaque, yet the fully transparent alpha should win:
        writeAndReadImageData("16x16x32-alpha-vs-mask", baos.toByteArray(),
                0xFF000000, 0x00000000);
    }

    public void testFullyTransparent32bitRGBA() throws Exception
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        BinaryOutputStream bos = new BinaryOutputStream(baos,
                BinaryOutputStream.BYTE_ORDER_LITTLE_ENDIAN);
        byte[] bitmap = new GeneratorFor32BitBitmaps().generate32bitRGBABitmap(
                0x00000000, 0x00FFFFFF, 0, true);
        writeICONDIR(bos, 0, 1, 1);
        writeICONDIRENTRY(bos, 16, 16, 0, 0, 1, 32, 40 + bitmap.length);
        writeBITMAPINFOHEADER(bos, 16, 2*16, 1, 32, 0, 0, 0);
        bos.write(bitmap);
        bos.flush();
        // Because every pixel is fully trasparent, ***ALPHA GETS IGNORED***:
        writeAndReadImageData("16x16x32-fully-transparent", baos.toByteArray(),
                0xFF000000, 0xFFFFFFFF);
    }

    private void writeAndReadImageData(String description, byte[] rawData,
            int foreground, int background) throws IOException,
            ImageReadException
    {
        // Uncomment to generate ICO files that can be tested with Windows:
        //File exportFile = new File("/tmp/" + description + ".ico");
        //IoUtils.writeToFile(rawData, exportFile);

        File tempFile = createTempFile("temp", ".ico");
        IoUtils.writeToFile(rawData, tempFile);

        BufferedImage dstImage = Sanselan.getBufferedImage(tempFile);

        assertNotNull(dstImage);
        assertTrue(dstImage.getWidth() == image[0].length);
        assertTrue(dstImage.getHeight() == image.length);

        verify(dstImage, foreground, background);
    }

    private void verify(BufferedImage data, int foreground, int background)
    {
        assertNotNull(data);
        assertTrue(data.getHeight() == image.length);

        for (int y = 0; y < data.getHeight(); y++)
        {
            assertTrue(data.getWidth() == image[y].length);
            for (int x = 0; x < data.getWidth(); x++)
            {
                int imageARGB = (image[y][x] == 1) ? foreground : background;
                int dataARGB = data.getRGB(x, y);

                if (imageARGB != dataARGB)
                {
                    Debug.debug("x: " + x + ", y: " + y + ", image: " + imageARGB
                            + " (0x" + Integer.toHexString(imageARGB) + ")"
                            + ", data: " + dataARGB + " (0x"
                            + Integer.toHexString(dataARGB) + ")");
                }
                assertTrue(imageARGB == dataARGB);
            }
        }
    }

}
