/**
 * @author Aurélie
 *
 */

package View;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

import Model.Classification;
import Model.IAcquisition;
import Model.IPoint;
import Model.IUser;
import Model.Model;
import Model.Point;
import Model.Pretraitement;

public class OngletIdentification extends JPanel {

	private static final long serialVersionUID = 1L;

	private MyJComboBox jCombo;

	private JPanel container;
	private JPanel gtop;
	private JPanel gtoptop;
	private JPanel gtopmid;
	private JPanel gtopbot;
	private JPanel gmid;
	private JPanel gbottop;
	private JPanel gbotmid;
	private JPanel gbotbot;
	private JPanel gbot;

	private JPanel drawingArea;

	private JLabel jl1 = new JLabel("Identification : ");
	private JLabel jl2 = new JLabel("Comparaison : ");
	private JLabel jl3 = new JLabel("Etes vous d'accord avec la reponse du systeme? ");
	private JLabel labelSystemAnswer = new JLabel();

	private JCheckBox jr1;
	private JCheckBox jr2;
	private JCheckBox jr3;
	private JCheckBox jr4;
	private JCheckBox faussaire;
	private JRadioButton jr5;
	private JRadioButton jr6;

	private ButtonGroup bg2 = new ButtonGroup();

	private JButton jb1;

	private JButton jb2;
	private JButton jb3;

	protected DrawingFrame df;

	private int drawingAreaHeight = 200;

	protected int source;

	private BufferedImage bf;

	private boolean isLastSignatureValid;


	public OngletIdentification(Model model) {

		container = new JPanel();
		container.setLayout(new BorderLayout());
		gtop = new JPanel();
		gtop.setLayout(new BorderLayout());
		gtop.setPreferredSize(new Dimension(600,210));
		gtoptop = new JPanel();
		gtoptop.setPreferredSize(new Dimension(600,70));
		gtopmid = new JPanel();
		gtopmid.setPreferredSize(new Dimension(600,80));
		gtopbot = new JPanel();
		gtopbot.setPreferredSize(new Dimension(600,60));


		//To add at this panel : Satisfaction ?
		gmid = new JPanel();
		gmid.setPreferredSize(new Dimension(600,drawingAreaHeight+10));


		//To add at this panel: Response 
		gbot = new JPanel();
		gbot.setLayout(new BorderLayout());
		gbot.setPreferredSize(new Dimension(600,330-drawingAreaHeight));
		gbottop = new JPanel();
		gbottop.setPreferredSize(new Dimension(600,(330-drawingAreaHeight)/3));
		gbotmid = new JPanel();
		gbotmid.setPreferredSize(new Dimension(600,(330-drawingAreaHeight)/3));
		gbotbot = new JPanel();
		gbotbot.setPreferredSize(new Dimension(600,(330-drawingAreaHeight)/3));


		jCombo = new MyJComboBox(model);		
		this.add(jCombo);

		model.addObserver(jCombo);

		jr1 = new JCheckBox("Vitesse");
		jr2 = new JCheckBox("Pression");
		jr3 = new JCheckBox("Position en x");
		jr4 = new JCheckBox("Position en y");
		faussaire = new JCheckBox("Faussaire");
		jr5 = new JRadioButton("Tablette");
		jr6 = new JRadioButton("DS");

		jr1.setSelected(true);
		jr2.setSelected(true);
		jr3.setSelected(true);
		jr4.setSelected(true);		

		gtoptop.add(jl1);
		gtoptop.add(jCombo);
		gtoptop.add(faussaire);

		gtopmid.add(jl2);
		gtopmid.add(jr1);
		gtopmid.add(jr2);
		gtopmid.add(jr3);
		gtopmid.add(jr4);


		jr5.setSelected(true);

		bg2.add(jr5);
		bg2.add(jr6);

		jb1 = new JButton("Signer");

		gtopbot.add(jr5);
		gtopbot.add(jr6);
		gtopbot.add(jb1);

		gtop.add(gtoptop, BorderLayout.NORTH);
		gtop.add(gtopmid, BorderLayout.CENTER);
		gtop.add(gtopbot, BorderLayout.SOUTH);



		container.add(gtop, BorderLayout.NORTH);


		drawingArea = new JPanel() {
			private static final long serialVersionUID = 1L;

			public void paintComponent(Graphics g) {
				if(bf != null)
					g.drawImage(bf, 0, 0, null); 
			}
		};

		gmid.add(drawingArea);

		Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
		double ratio = dim.getWidth()/dim.getHeight();

		drawingArea.setPreferredSize( new Dimension((int) (drawingAreaHeight*ratio), drawingAreaHeight));

		jb1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {

				if(jr6.isSelected()) {
					source = DrawingFrame.SOURCE_DS;
				} else {
					source = DrawingFrame.SOURCE_TABLET;
				}				

				df = new DrawingFrame(OngletIdentification.this, 1, source);

			}
		});

		labelSystemAnswer.setFont(new Font("Serif", Font.BOLD, 26));
		gbottop.add(labelSystemAnswer);


		Font newButtonFont = new Font(jl3.getFont().getName(),jl3.getFont().getStyle(),14);  
		jl3.setFont(newButtonFont);  

		jb2 = new JButton("Je suis d'accord");
		jb2.setForeground(Color.GREEN);

		jb3 = new JButton("Je ne suis pas d'accord");
		jb3.setForeground(Color.RED);

		jb2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				addSignatureLog(true);
			}
		});
		jb3.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				addSignatureLog(false);
			}
		});

		gbotmid.add(jl3);
		gbotbot.add(jb2);
		gbotbot.add(jb3);	

		gbot.add(gbottop, BorderLayout.NORTH);
		gbot.add(gbotmid, BorderLayout.CENTER);
		gbot.add(gbotbot, BorderLayout.SOUTH);

		container.add(gmid,BorderLayout.CENTER);

		gbot.setVisible(false);

		container.add(gbot,BorderLayout.SOUTH);

		this.add(container);
	}

	protected void addSignatureLog(boolean isApprouved) {
		gbot.setVisible(false);

		try {
			IUser user = (IUser) jCombo.getSelectedItem();

			IAcquisition acq = user.getUserSignature().addAcquisition(true);
			acq.addPoints(df.getAcquisitions().get(0));
			acq.addLog(isLastSignatureValid, isApprouved);


		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	class MyJComboBox extends JComboBox<IUser> implements Observer {

		private static final long serialVersionUID = 6059418981592900531L;

		public MyJComboBox(Model model) {
			List<IUser> usersList = model.getUserList();

			for (IUser u : usersList) {
				this.addItem(u);
			}
		}

		public void update(Observable o, Object arg) {
			if(o instanceof Model) {
				this.removeAllItems();
				Model model = (Model) o;
				for(IUser u : model.getUserList()) {
					this.addItem(u);
				}
			}
		}

	}

	public void setAcquisitionWorked() throws IOException {
		if(df != null && df.getAcquisitions().size() == 1) {
						
			for(IPoint p : df.getAcquisitions().get(0)) {
				System.out.println((Point)p);
			}
			
			gbot.setVisible(true);
			//////////////// Lien avec algorithmes //////////////////////////
			// Personne que l'on prétend être
			IUser user = (IUser) jCombo.getSelectedItem();	
			
			Pretraitement.init();
			
			// Pretraitement des acquisitions de cette personne
			Pretraitement.pretraitementBD(user.getUserSignature(), 5, false);
			// Pretraitement de la nouvelle acquisition
			Pretraitement.pretraitementNouvelleAcquisition(df.getAcquisitions().get(0), false);
			// Récupération des options de comparaisons
			boolean[] attributes = {jr1.isSelected(),jr2.isSelected(),jr3.isSelected(),jr4.isSelected()};
			// Récupétation des données obtenues après comparaison
			Pretraitement.createIdentificationARFF(attributes);
			// Application du modèle et récupération des décisions prises
			double[] decisions = Classification.takeDecision("apprentissagebest.arff");
			// Calcul du seuil d'acceptation
			int nbAccept = 0;
			double seuil = 0;
			for (int i=0; i<decisions.length; i++) {
				if (decisions[i] == 1) {
					nbAccept++;
				}
				seuil = 1.*nbAccept/decisions.length;
			}
			// Si la nouvelle acquisition est reconnue comme équivalente à au moins 3 des 5 acquisitions
			
			isLastSignatureValid = (seuil >= 4./5);
			
			System.out.println("System answer : for "+user.getUserFirstName()+" isValid ? "+isLastSignatureValid);
			
			///////////////////////////////////////////////////////////////////
			if(isLastSignatureValid) {
				labelSystemAnswer.setText("Vous avez bien été identifié");
				labelSystemAnswer.setForeground(Color.GREEN);
			} else {
				labelSystemAnswer.setText("Vous avez mal été identifié");
				labelSystemAnswer.setForeground(Color.RED);	
			}
			
			drawSignature(df.getAcquisitions().get(0));

			SignatureObservable.Instance().SignatureNotify(df.getAcquisitions().get(0));
			
		}
	}

	private void drawSignature(List<IPoint> list) {

		drawingArea.setBackground(Color.WHITE);

		IPoint lastPoint = null;
		IPoint tempPoint1;
		IPoint tempPoint2;


		Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
		double ratioWindow = dim.getWidth()/dim.getHeight();
		int windowWidth = (source == DrawingFrame.SOURCE_DS) ? 
				drawingAreaHeight : 
					((int)(drawingAreaHeight*ratioWindow))+1;

		bf = new BufferedImage(windowWidth, drawingAreaHeight, BufferedImage.TYPE_INT_RGB);

		Graphics2D g2d2 = bf.createGraphics();

		g2d2.setRenderingHint(RenderingHints.KEY_RENDERING,
				RenderingHints.VALUE_RENDER_QUALITY);
		g2d2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
				RenderingHints.VALUE_STROKE_PURE);
		g2d2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);	

		g2d2.setColor(Color.white);
		g2d2.fillRect(0, 0, windowWidth,drawingAreaHeight);


		double ratio = (source == DrawingFrame.SOURCE_DS) ? 
				drawingAreaHeight/1000. :
					drawingAreaHeight/dim.getHeight();


		for(IPoint point : list) {
			if(lastPoint != null && point.getTime() - lastPoint.getTime() < DrawingFrame.delayBetweenLines) {
				tempPoint1 = new Point(point);
				tempPoint2 = new Point(lastPoint);

				tempPoint1.setPoint(new Point2D.Double(tempPoint1.getPoint().x * ratio, tempPoint1.getPoint().y * ratio));
				tempPoint2.setPoint(new Point2D.Double(tempPoint2.getPoint().x * ratio, tempPoint2.getPoint().y * ratio));

				g2d2.setColor(Color.BLACK);
				g2d2.draw(new Line2D.Double(tempPoint1.getPoint(), tempPoint2.getPoint()));
			}

			lastPoint = point;
		}

		g2d2.dispose();
		this.revalidate();
		this.repaint();
		drawingArea.repaint();
		drawingArea.revalidate();
	}

	public IUser getUser() {
		if (jCombo!=null) {
			return (IUser) jCombo.getSelectedItem();
		}
		return null;

	}

	public boolean getFaussaire() {
		return faussaire.isSelected();
	}

}
