package presenter.evaluation;
import jdk.nashorn.internal.scripts.JD;
import model.Line;
import org.opencv.core.*;
import org.opencv.highgui.*;
import org.opencv.imgproc.Imgproc;
import presenter.Presenter;

import javax.swing.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.File;
import java.util.ArrayList;
import java.util.Observable;

/**
 * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
 *
 * @Author: Armin Wolf
 * @Email: a_wolf28@uni-muenster.de
 * @Date: 17.09.2017.
 */
public class PictureProcessor extends Observable{

    private Mat image;
    private Mat contour;
    private Presenter presenter;
    private File file;
    private ArrayList<MatOfPoint> contours;

    public PictureProcessor(Presenter presenter, File file)  {
        this.file = file;
        this.presenter = presenter;
    }

    public void run(){
        image = Highgui.imread(file.getAbsolutePath());
        contour = process(image);
        createInputData();
    }

    private Mat process(Mat image){
        Mat threshold = new Mat(image.width(), image.height(), CvType.CV_8UC1);
        Mat source = new Mat(image.width(), image.height(), CvType.CV_8UC1);
        Imgproc.cvtColor(image, source, Imgproc.COLOR_BGR2GRAY);
        Imgproc.blur(source, threshold, new Size(3,3));
        Imgproc.Canny(threshold, source,300,600,5,true);

        //Konturen berechnen und filtern
        contours = new ArrayList<>();
        Imgproc.findContours(source, contours, new Mat(), Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0,0));
        Mat viscont = new Mat(source.size(), source.type());
        for (int i=0;i<contours.size();i++) {
            if (Imgproc.contourArea(contours.get(i)) > 100) {
                Imgproc.drawContours(viscont, contours, i, new Scalar(255, 255, 100), -1);
            }
        }
        SwingUtilities.invokeLater(() -> {
            JDialog dialog = new JDialog();
            dialog.setSize(1100,700);
            dialog.add(new JLabel(new ImageIcon(toBufferedImage(viscont))));
            dialog.setVisible(true);
        });
        return source;
    }


    private BufferedImage toBufferedImage(Mat m) {
        int type = BufferedImage.TYPE_BYTE_GRAY;
        if (m.channels() > 1) {
            type = BufferedImage.TYPE_3BYTE_BGR;
        }
        int bufferSize = m.channels() * m.cols() * m.rows();
        byte[] b = new byte[bufferSize];
        m.get(0, 0, b); // get all the pixels
        BufferedImage image = new BufferedImage(m.cols(), m.rows(), type);
        final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
        System.arraycopy(b, 0, targetPixels, 0, b.length);
        return image;

    }

    private void createInputData(){
        Thread t = new Thread(() -> {
            int id = 0;
            for (int j=0;j<contours.size();j++){
                Point[] p = contours.get(j).toArray();
                if (p.length > 200) {
                    for (int i = 0; i < p.length; i++) {
                        Line line = new Line(-1 * (500 - p[i].x), p[i].y);
                        line.setId("" + id++);
                        presenter.getModel().getLines().add(line);
                    }
                }
            }

            setChanged();
            String[] msg = {"import-picture"};
            notifyObservers(msg);
        });
        t.start();
        try {
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}