/*
 * Copyright (C) 2014 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 android.theme.cts;

import com.android.ddmlib.Log;
import com.android.ddmlib.Log.LogLevel;
import com.android.tradefed.util.Pair;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.lang.String;
import java.util.concurrent.Callable;

import javax.imageio.ImageIO;

/**
 * Compares the images generated by the device with the reference images.
 */
public class ComparisonTask implements Callable<Pair<String, File>> {
    private static final String TAG = "ComparisonTask";

    /** Maximum allowed LAB distance between two pixels. */
    private static final double IMAGE_THRESHOLD = 0.76;

    /** Neutral gray for blending colors. */
    private static final int GRAY = 0xFF808080;

    /** Maximum allowable number of consecutive failed pixels. */
    private static final int MAX_CONSECUTIVE_FAILURES = 1;

    private final String mName;
    private final File mExpected;
    private final File mActual;

    public ComparisonTask(String name, File expected, File actual) {
        mName = name;
        mExpected = expected;
        mActual = actual;
    }

    public Pair<String, File> call() {
        try {
            final BufferedImage expected = ImageIO.read(mExpected);
            final BufferedImage actual = ImageIO.read(mActual);
            if (!compare(expected, actual, IMAGE_THRESHOLD)) {
                final File diff = File.createTempFile("diff_" + mExpected.getName(), ".png");
                createDiff(expected, actual, diff);
                return new Pair<>(mName, diff);
            }
        } catch (IOException e) {
            Log.logAndDisplay(LogLevel.ERROR, TAG, e.toString());
            e.printStackTrace();
        }

        return null;
    }

    private static int getAlphaScaledBlue(final int color) {
        return (color & 0x000000FF) * getAlpha(color) / 255;
    }

    private static int getAlphaScaledGreen(final int color) {
        return ((color & 0x0000FF00) >> 8) * getAlpha(color) / 255;
    }

    private static int getAlphaScaledRed(final int color) {
        return ((color & 0x00FF0000) >> 16) * getAlpha(color) / 255;
    }

    private static int getAlpha(final int color) {
        // use logical shift for keeping an unsigned value
        return (color & 0xFF000000) >>> 24;
    }


    /**
     * Verifies that the pixels of reference and generated images are similar
     * within a specified threshold.
     *
     * @param reference expected image
     * @param generated actual image
     * @param threshold maximum difference per channel
     * @return {@code true} if the images are similar, false otherwise
     */
    private static boolean compare(BufferedImage reference, BufferedImage generated,
            double threshold) {
        final int w = generated.getWidth();
        final int h = generated.getHeight();
        if (w != reference.getWidth() || h != reference.getHeight()) {
            return false;
        }

        double maxDist = 0;
        for (int i = 0; i < w; i++) {
            int consecutive = 0;

            for (int j = 0; j < h; j++) {
                final int p1 = reference.getRGB(i, j);
                final int p2 = generated.getRGB(i, j);
                final double dist = computeLabDistance(p1, p2);
                if (dist > threshold) {
                    System.err.println("fail " + dist);

                    consecutive++;

                    if (consecutive > MAX_CONSECUTIVE_FAILURES) {
                        System.err.println("consecutive fail");
                        return false;
                    }
                } else {
                    consecutive = 0;
                }
            }
        }
        return true;
    }

    /**
     * Returns the perceptual difference score (lower is better) for the
     * provided ARGB pixels.
     */
    private static double computeLabDistance(int p1, int p2) {
        // Blend with neutral gray to account for opacity.
        p1 = ColorUtils.blendSrcOver(p1, GRAY);
        p2 = ColorUtils.blendSrcOver(p2, GRAY);

        // Convert to LAB.
        double[] lab1 = new double[3];
        double[] lab2 = new double[3];
        ColorUtils.colorToLAB(p1, lab1);
        ColorUtils.colorToLAB(p2, lab2);

        // Compute the distance
        double dist = 0;
        for (int i = 0; i < 3; i++) {
            double delta = lab1[i] - lab2[i];
            dist += delta * delta;
        }
        return Math.sqrt(dist);
    }

    private static void createDiff(BufferedImage expected, BufferedImage actual, File out)
            throws IOException {
        final int w1 = expected.getWidth();
        final int h1 = expected.getHeight();
        final int w2 = actual.getWidth();
        final int h2 = actual.getHeight();
        final int width = Math.max(w1, w2);
        final int height = Math.max(h1, h2);

        // The diff will contain image1, image2 and the difference between the two.
        final BufferedImage diff = new BufferedImage(
                width * 3, height, BufferedImage.TYPE_INT_ARGB);

        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                final boolean inBounds1 = i < w1 && j < h1;
                final boolean inBounds2 = i < w2 && j < h2;
                int colorExpected = Color.WHITE.getRGB();
                int colorActual = Color.WHITE.getRGB();
                int colorDiff;
                if (inBounds1 && inBounds2) {
                    colorExpected = expected.getRGB(i, j);
                    colorActual = actual.getRGB(i, j);
                    colorDiff = colorExpected == colorActual ? colorExpected : Color.RED.getRGB();
                } else if (inBounds1 && !inBounds2) {
                    colorExpected = expected.getRGB(i, j);
                    colorDiff = Color.BLUE.getRGB();
                } else if (!inBounds1 && inBounds2) {
                    colorActual = actual.getRGB(i, j);
                    colorDiff = Color.GREEN.getRGB();
                } else {
                    colorDiff = Color.MAGENTA.getRGB();
                }

                int x = i;
                diff.setRGB(x, j, colorExpected);
                x += width;
                diff.setRGB(x, j, colorActual);
                x += width;
                diff.setRGB(x, j, colorDiff);
            }
        }

        ImageIO.write(diff, "png", out);
    }

}
