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

import java.io.IOException;

import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.common.ImageBuilder;
import org.apache.commons.imaging.formats.bmp.BmpHeaderInfo;

public class PixelParserRle extends PixelParser
{

    public PixelParserRle(BmpHeaderInfo bhi, byte ColorTable[],
            byte ImageData[])
    {
        super(bhi, ColorTable, ImageData);

    }

    private int getSamplesPerByte() throws ImageReadException
    {
        if (bhi.bitsPerPixel == 8)
            return 1;
        else if (bhi.bitsPerPixel == 4)
            return 2;
        else
            throw new ImageReadException("BMP RLE: bad BitsPerPixel: "
                    + bhi.bitsPerPixel);
    }

    private int[] convertDataToSamples(int data) throws ImageReadException
    {
        int rgbs[];
        if (bhi.bitsPerPixel == 8)
        {
            rgbs = new int[1];
            rgbs[0] = getColorTableRGB(data);
            //            pixels_written = 1;
        }
        else if (bhi.bitsPerPixel == 4)
        {
            rgbs = new int[2];
            int sample1 = data >> 4;
            int sample2 = 0x0f & data;
            rgbs[0] = getColorTableRGB(sample1);
            rgbs[1] = getColorTableRGB(sample2);
            //            pixels_written = 2;
        }
        else
            throw new ImageReadException("BMP RLE: bad BitsPerPixel: "
                    + bhi.bitsPerPixel);

        return rgbs;
    }

    private int processByteOfData(int rgbs[], int repeat, int x, int y,
            int width, int height, ImageBuilder imageBuilder)
    {
        //                int rbg
        int pixels_written = 0;
        for (int i = 0; i < repeat; i++)
        {

            if ((x >= 0) && (x < width) && (y >= 0) && (y < height))
            {
                //                    int rgb = 0xff000000;
                //                    rgb = getNextRGB();
                int rgb = rgbs[i % rgbs.length];
                //                                bi.setRGB(x, y, rgb);
                imageBuilder.setRGB(x, y, rgb);
                //                                bi.setRGB(x, y, 0xff00ff00);
            }
            else
            {
                System.out.println("skipping bad pixel (" + x + "," + y + ")");
            }

            x++;
            pixels_written++;
        }

        return pixels_written;
    }

    @Override
    public void processImage(ImageBuilder imageBuilder) throws ImageReadException,
            IOException
    {
        int count = 0;
        int width = bhi.width;
        int height = bhi.height;
        int x = 0, y = height - 1;

        //        bfp.setDebug(true);

        boolean done = false;
        while (!done)
        {
            count++;
            //            if (count > 100)
            //                return;

            int a = 0xff & bfp.readByte("RLE (" + x + "," + y + ") a", is,
                    "BMP: Bad RLE");
            //                baos.write(a);
            int b = 0xff & bfp.readByte("RLE (" + x + "," + y + ")  b", is,
                    "BMP: Bad RLE");
            //                baos.write(b);

            if (a == 0)
            {
                switch (b)
                {
                    case 0 : // EOL
                    {
                        //                        System.out.println("EOL");
                        y--;
                        x = 0;
                    }
                        break;
                    case 1 : // EOF
                        //                        System.out
                        //                                .println("xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
                        done = true;
                        break;
                    case 2 : {
                        //                        System.out
                        //                                .println("xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
                        int c = 0xff & bfp
                                .readByte("RLE c", is, "BMP: Bad RLE");
                        //                            baos.write(c);
                        int d = 0xff & bfp
                                .readByte("RLE d", is, "BMP: Bad RLE");
                        //                            baos.write(d);

                    }
                        break;
                    default : {
                        //                        System.out
                        //                                .println("xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");

                        int SamplesPerByte = getSamplesPerByte();
                        int size = b / SamplesPerByte;
                        if ((b % SamplesPerByte) > 0)
                            size++;
                        if ((size % 2) != 0)
                            size++;

                        //                        System.out.println("b: " + b);
                        //                        System.out.println("size: " + size);
                        //                        System.out.println("SamplesPerByte: " + SamplesPerByte);

                        byte bytes[] = bfp.readByteArray("bytes", size, is,
                                "RLE: Absolute Mode");

                        int remaining = b;

                        //                        while(true)
                        for (int i = 0; remaining > 0; i++)
                        //                                for (int i = 0; i < bytes.length; i++)
                        {
                            int samples[] = convertDataToSamples(0xff & bytes[i]);
                            int towrite = Math.min(remaining, SamplesPerByte);
                            //                            System.out.println("remaining: " + remaining);
                            //                            System.out.println("SamplesPerByte: "
                            //                                    + SamplesPerByte);
                            //                            System.out.println("towrite: " + towrite);
                            int written = processByteOfData(samples, towrite,
                                    x, y, width, height, imageBuilder);
                            //                            System.out.println("written: " + written);
                            //                            System.out.println("");
                            x += written;
                            remaining -= written;
                        }
                        //                            baos.write(bytes);
                    }
                        break;
                }
            }
            else
            {
                int rgbs[] = convertDataToSamples(b);

                x += processByteOfData(rgbs, a, x, y, width, height, imageBuilder);
                //                    x += processByteOfData(b, a, x, y, width, height, bi);

            }
        }

    }
}