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

import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PaletteFactory
{
    private static final boolean debug = false;

    public void makePaletteFancy(BufferedImage src)
    {
        //         map what rgb values have been used

        byte rgbmap[] = new byte[256 * 256 * 32];
        for (int i = 0; i < rgbmap.length; i++)
            rgbmap[i] = 0;

        int width = src.getWidth();
        int height = src.getHeight();

        for (int y = 0; y < height; y++)
            for (int x = 0; x < width; x++)
            {
                int argb = src.getRGB(x, y);
                int rggbb = 0x1fffff & argb;
                int highred = 0x7 & (argb >> 21);
                int mask = 1 << highred;
                rgbmap[rggbb] |= mask;
            }

        int count = 0;
        for (int i = 0; i < rgbmap.length; i++)
        {
            int eight = 0xff & rgbmap[i];
            if ((i < 3) || ((i - rgbmap.length) > -3))
            {
            }
            for (int j = 0; j < 8; j++)
            {
                int mask = 1 << (7 - j);
                int bit = eight & mask;
                if (bit > 0)
                    count++;

            }
        }

        if (debug)
            System.out.println("Used colors: " + count);

        int colormap[] = new int[count];
        int mapsize = 0;
        for (int i = 0; i < rgbmap.length; i++)
        {
            int eight = 0xff & rgbmap[i];

            for (int j = 0; j < 8; j++)
            {
                int mask = 1 << (7 - j);
                int bit = eight & mask;

                if (bit > 0)
                {
                    int rgb = i | ((7 - j) << 21);

                    if (mapsize < colormap.length)
                        colormap[mapsize] = rgb;
                    mapsize++;
                }
            }
        }

        if (debug)
            System.out.println("mapsize: " + mapsize);

        //        for (int i = 0; i < colormap.length; i++)
        //        {
        //            int rgb = colormap[i];
        //        }

    }

    private int pixelToQuantizationTableIndex(int argb, int precision)
    {
        int result = 0;
        int precision_mask = (1 << precision) - 1;

        for (int i = 0; i < components; i++)
        {
            int sample = argb & 0xff;
            argb >>= 8;

            sample >>= (8 - precision);
            result = (result << precision) | (sample & precision_mask);
        }

        return result;
    }

    private int getFrequencyTotal(int table[], int mins[], int maxs[],
            int precision)
    {
        int sum = 0;

        for (int blue = mins[2]; blue <= maxs[2]; blue++)
        {
            int b = (blue << (2 * precision));
            for (int green = mins[1]; green <= maxs[1]; green++)
            {
                int g = (green << (1 * precision));

                for (int red = mins[0]; red <= maxs[0]; red++)
                {
                    int index = b | g | red;

                    sum += table[index];
                }
            }
        }

        return sum;
    }

    private DivisionCandidate finishDivision(int table[],
            ColorSpaceSubset subset, int component, int precision, int sum,
            int slice)
    {
        if (debug)
            subset.dump("trying (" + component + "): ");

        int total = subset.total;

        if ((slice < subset.mins[component])
                || (slice >= subset.maxs[component]))
        {
            return null;
        }

        if ((sum < 1) || (sum >= total))
        {
            return null;
        }

        int remainder = total - sum;
        if ((remainder < 1) || (remainder >= total))
        {
            return null;
        }

        //        List result = new ArrayList();

        int slice_mins[] = new int[subset.mins.length];
        System.arraycopy(subset.mins, 0, slice_mins, 0, subset.mins.length);
        int slice_maxs[] = new int[subset.maxs.length];
        System.arraycopy(subset.maxs, 0, slice_maxs, 0, subset.maxs.length);

        slice_maxs[component] = slice;
        slice_mins[component] = slice + 1;

        if (debug)
        {
            System.out.println("total: " + total);
            System.out.println("first total: " + sum);
            System.out.println("second total: " + (total - sum));
            //            System.out.println("start: " + start);
            //            System.out.println("end: " + end);
            System.out.println("slice: " + slice);

        }

        ColorSpaceSubset first = new ColorSpaceSubset(sum, precision,
                subset.mins, slice_maxs, table);
        ColorSpaceSubset second = new ColorSpaceSubset(total - sum, precision,
                slice_mins, subset.maxs, table);

        return new DivisionCandidate(subset, first, second);

    }

    private List<DivisionCandidate> divideSubset2(int table[], ColorSpaceSubset subset,
                                                  int component, int precision)
    {
        if (debug)
            subset.dump("trying (" + component + "): ");

        int total = subset.total;

        int slice_mins[] = new int[subset.mins.length];
        System.arraycopy(subset.mins, 0, slice_mins, 0, subset.mins.length);
        int slice_maxs[] = new int[subset.maxs.length];
        System.arraycopy(subset.maxs, 0, slice_maxs, 0, subset.maxs.length);

        int sum1 = 0, sum2;
        int slice1, slice2;
        int last = 0;

        {
            for (slice1 = subset.mins[component]; slice1 != subset.maxs[component] + 1; slice1++)
            {

                slice_mins[component] = slice1;
                slice_maxs[component] = slice1;

                last = getFrequencyTotal(table, slice_mins, slice_maxs,
                        precision);

                sum1 += last;

                if (sum1 >= (total / 2))
                    break;
            }

            sum2 = sum1 - last;
            slice2 = slice1 - 1;

        }

        DivisionCandidate dc1 = finishDivision(table, subset, component,
                precision, sum1, slice1);
        DivisionCandidate dc2 = finishDivision(table, subset, component,
                precision, sum2, slice2);

        List<DivisionCandidate> result = new ArrayList<DivisionCandidate>();

        if (dc1 != null)
            result.add(dc1);
        if (dc2 != null)
            result.add(dc2);

        return result;
    }

    private DivisionCandidate divideSubset2(int table[],
            ColorSpaceSubset subset, int precision)
    {
        List<DivisionCandidate> dcs = new ArrayList<DivisionCandidate>();

        dcs.addAll(divideSubset2(table, subset, 0, precision));
        dcs.addAll(divideSubset2(table, subset, 1, precision));
        dcs.addAll(divideSubset2(table, subset, 2, precision));

        DivisionCandidate best_v = null;
        //        int best_split
        double best_score = Double.MAX_VALUE;

        for (int i = 0; i < dcs.size(); i++)
        {
            DivisionCandidate dc = dcs.get(i);

            ColorSpaceSubset first = dc.dst_a;
            ColorSpaceSubset second = dc.dst_b;
            int area1 = first.total;
            int area2 = second.total;

            int diff = Math.abs(area1 - area2);
            double split = ((double) diff) / ((double) Math.max(area1, area2));

            double score = split;

            if (best_v == null)
            {
                best_v = dc;
                best_score = score;
            }
            else if (score < best_score)
            {
                best_v = dc;
                best_score = score;
            }

        }

        return best_v;
    }

    public static final int components = 3; // in bits

    private static class DivisionCandidate
    {
        //        private final ColorSpaceSubset src;
        private final ColorSpaceSubset dst_a, dst_b;

        public DivisionCandidate(ColorSpaceSubset src, ColorSpaceSubset dst_a,
                ColorSpaceSubset dst_b)
        {
            //            this.src = src;
            this.dst_a = dst_a;
            this.dst_b = dst_b;
        }
    }

    private List<ColorSpaceSubset> divide(List<ColorSpaceSubset> v, int desired_count, int table[],
                                          int precision)
    {
        List<ColorSpaceSubset> ignore = new ArrayList<ColorSpaceSubset>();

        int count = 0;
        while (true)
        {
            count++;

            if (debug)
                System.out.println("cycle(" + count + "): " + v.size()
                        + " done");

            int max_area = -1;
            ColorSpaceSubset max_subset = null;

            for (int i = 0; i < v.size(); i++)
            {
                ColorSpaceSubset subset = v.get(i);
                if (ignore.contains(subset))
                    continue;
                int area = subset.total;

                if (max_subset == null)
                {
                    max_subset = subset;
                    max_area = area;
                }
                else if (area > max_area)
                {
                    max_subset = subset;
                    max_area = area;
                }
            }

            if (max_subset == null)
            {
                return v;
            }
            if (debug)
                System.out.println("\t" + "area: " + max_area);

            {

                DivisionCandidate dc = divideSubset2(table, max_subset,
                        precision);
                if (dc != null)
                {
                    v.remove(max_subset);
                    v.add(dc.dst_a);
                    v.add(dc.dst_b);
                }
                else
                    ignore.add(max_subset);
            }

            if (v.size() == desired_count)
                return v;
        }

        //        return result;
    }

    public Palette makePaletteQuantized(BufferedImage src, int max)
    {
        int precision = 6; // in bits

        int table_scale = precision * components;
        int table_size = 1 << table_scale;
        int table[] = new int[table_size];

        int width = src.getWidth();
        int height = src.getHeight();

        List<ColorSpaceSubset> subsets = new ArrayList<ColorSpaceSubset>();
        ColorSpaceSubset all = new ColorSpaceSubset(width * height, precision);
        subsets.add(all);

        int pre_total = getFrequencyTotal(table, all.mins, all.maxs, precision);
        if (debug)
            System.out.println("pre total: " + pre_total);

        { // step 1: count frequency of colors

            for (int y = 0; y < height; y++)
                for (int x = 0; x < width; x++)
                {
                    int argb = src.getRGB(x, y);

                    int index = pixelToQuantizationTableIndex(argb, precision);

                    table[index]++;
                }
        }

        int all_total = getFrequencyTotal(table, all.mins, all.maxs, precision);
        if (debug)
        {
            System.out.println("all total: " + all_total);

            System.out.println("width * height: " + (width * height));
        }

        subsets = divide(subsets, 256, table, precision);

        if (debug)
        {
            System.out.println("subsets: " + subsets.size());
            System.out.println("width*height: " + width * height);
        }

        for (int i = 0; i < subsets.size(); i++)
        {
            ColorSpaceSubset subset = subsets.get(i);

            subset.setAverageRGB(table);

            if (debug)
                subset.dump(i + ": ");
        }

        Collections.sort(subsets);

        return new QuantizedPalette(subsets, precision);
    }

    public SimplePalette makePaletteSimple(BufferedImage src, int max)
    // This is not efficient for large values of max, say, max > 256;
    {
        Map<String, String> map = new HashMap<String, String>();
        int rgbs[] = new int[max];
        int rgb_count = 0;

        int width = src.getWidth();
        int height = src.getHeight();

        for (int y = 0; y < height; y++)
            for (int x = 0; x < width; x++)
            {
                int argb = src.getRGB(x, y);
                int rgb = 0xffffff & argb;

                String key = "" + rgb;
                if (null == map.get(key))
                {
                    if (rgb_count == max)
                        return null;

                    rgbs[rgb_count] = rgb;
                    map.put(key, key);
                    rgb_count++;
                }
            }

        int result[] = new int[rgb_count];
        System.arraycopy(rgbs, 0, result, 0, rgb_count);
        Arrays.sort(result);

        //        return result;
        return new SimplePalette(result);
    }

    public boolean isGrayscale(BufferedImage src)
    {
        int width = src.getWidth();
        int height = src.getHeight();

        if (ColorSpace.TYPE_GRAY == src.getColorModel().getColorSpace()
                .getType())
            return true;

        for (int y = 0; y < height; y++)
            for (int x = 0; x < width; x++)
            {
                int argb = src.getRGB(x, y);

                int red = 0xff & (argb >> 16);
                int green = 0xff & (argb >> 8);
                int blue = 0xff & (argb >> 0);

                if (red != green || red != blue)
                    return false;
            }

        return true;
    }

    public boolean hasTransparency(BufferedImage src)
    {
        return hasTransparency(src, 255);
    }

    public boolean hasTransparency(BufferedImage src, int threshold)
    {
        int width = src.getWidth();
        int height = src.getHeight();

        if (!src.getColorModel().hasAlpha())
            return false;

        for (int y = 0; y < height; y++)
            for (int x = 0; x < width; x++)
            {
                int argb = src.getRGB(x, y);
                int alpha = 0xff & (argb >> 24);
                if (alpha < threshold)
                    return true;
            }

        return false;
    }

    public int countTrasparentColors(int rgbs[])
    {
        int first = -1;

        for (int i = 0; i < rgbs.length; i++)
        {
            int rgb = rgbs[i];
            int alpha = 0xff & (rgb >> 24);
            if (alpha < 0xff)
            {
                if (first < 0)
                {
                    first = rgb;
                }
                else if (rgb != first)
                    return 2; // more than one transparent color;
            }
        }

        if (first < 0)
            return 0;
        return 1;
    }

    public int countTransparentColors(BufferedImage src)
    {
        ColorModel cm = src.getColorModel();
        if (!cm.hasAlpha())
            return 0;

        int width = src.getWidth();
        int height = src.getHeight();

        int first = -1;

        for (int y = 0; y < height; y++)
            for (int x = 0; x < width; x++)
            {
                int rgb = src.getRGB(x, y);
                int alpha = 0xff & (rgb >> 24);
                if (alpha < 0xff)
                {
                    if (first < 0)
                    {
                        first = rgb;
                    }
                    else if (rgb != first)
                        return 2; // more than one transparent color;
                }
            }

        if (first < 0)
            return 0;
        return 1;
    }

}