package imagetest;

import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelReader;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Stage;

/**
 *
 * @author abrygin
 */
public class ImageTest extends Application {

    @Override
    public void start(Stage primaryStage) {

        Parameters param = this.getParameters();

        List<String> cmd = param.getRaw();

        String image_dir = "images";

        if (!cmd.isEmpty()) {
            image_dir = cmd.get(0);
        }

        System.out.println("Look for images...");
        prepareImagePairs(image_dir);

        if (pairs.isEmpty()) {
            System.out.println("No images found...");
        } else {
            for (Pair p : pairs) {
                System.out.println(p);
            }
        }

        Text msg = new Text("Test PASSED");

        ImageView v = checkImages();

        StackPane root = new StackPane();
        if (v != null) {
            root.getChildren().add(v);
        } else {
            root.getChildren().add(msg);
        }
        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Image Test");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * The main() method is ignored in correctly deployed JavaFX application.
     * main() serves only as fallback in case the application can not be
     * launched through deployment artifacts, e.g., in IDEs with limited FX
     * support. NetBeans ignores main().
     *
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException {
        launch(args);
    }

    private static ImageView checkImages() {
        if (pairs.isEmpty()) {
            return null;
        }

        for (Pair p : pairs) {
            ImageView v = p.check();
            if (v != null) {
                return v;
            }
        }
        return null;
    }

    private static void prepareImagePairs(String image_dir) {
        File dir = new File(image_dir);

        File[] jpgs = dir.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(".jpg");
            }
        });

        for (File j : jpgs) {
            String p = j.getAbsolutePath();
            File png = new File(p.substring(0, p.length() - 4) + ".png");
            System.out.println("Look for :" + png.getAbsolutePath());

            if (png.isFile()) {
                Pair pair = new Pair();
                pair.jpg = j;
                pair.png = png;
                pairs.add(pair);
            }
        }
    }

    private static List<Pair> pairs = new ArrayList<>();

    static class Pair {
        File jpg;
        File png;

        public ImageView check() {
            System.out.println("Image: " + jpg.getAbsolutePath());
            try {
            Image iPng = new Image(new FileInputStream(png));
            Image iJpg = new Image(new FileInputStream(jpg));

            int x = (int)iPng.getWidth() / 2;
            int h = (int)iPng.getHeight();
            int dY = h / 10;
            if (dY == 0) {
                dY= 5;
            }

            PixelReader pngPixels = iPng.getPixelReader();
            PixelReader jpgPixels = iJpg.getPixelReader();
            for (int y = 5; y < h; y += dY) {
                Color j = jpgPixels.getColor(x, y);
                Color p = pngPixels.getColor(x, y);

                System.out.println("png: " + p + "; jpg: " + j);

                if (!isSimilar(j, p)) {
                    return new ImageView(iJpg);
                }

            }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        private boolean isSimilar(Color a, Color b) {
            final double delta = 0.05;

            double dR = Math.abs(a.getRed() - b.getRed());
            double dG = Math.abs(a.getGreen() - b.getGreen());
            double dB = Math.abs(a.getBlue() - b.getBlue());
            double dA = Math.abs(a.getOpacity() - b.getOpacity());
            boolean res =  dR < delta &&
                    dG < delta &&
                    dB < delta &&
                    dA < delta;

            if (!res) {
                System.out.printf("Difference: r:%.2f, g:%.2f, b:%.2f, a:%.2f\n",
                        dR, dG, dB, dA);
            }
            return res;
        }

    }
}
