package gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.net.InetAddress;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultCaret;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;

import controller.Agent;
import controller.DataBase;
import model.Contact;
import model.MessageAffichage;
import network.TCPChat;
import server.Request;

import java.awt.*;

public class FenetreChat extends JFrame implements PropertyChangeListener{
	
	private static FenetreChat instance = null;
	
	public static FenetreChat getInstance(Agent agent, String userString) throws IOException {
		synchronized (FenetreChat.class) {
			FenetreChat fc = instance;
			if(fc == null) {
				fc = new FenetreChat(agent, userString);
			}
			return fc;
		}
	}
	
	static JFrame frame;
	static Agent agent;
	static Contact dest; //destinataire du message
	Contact user; //utilisateur
	
	WindowAdapter wa;
	JPanel panel;
	static JTextArea text;
	JButton envoyer;

	private TCPChat t=null;
	
    static StyledDocument doc;
    private static boolean ouvert=false;
	
	
	private FenetreChat(Agent agent, String userString) throws IOException {
		FenetreChat.ouvert=true;
		
		this.frame = new JFrame("Fenetre Chat avec "+ userString);
		this.agent = agent;
		this.user = agent.getUser();
		this.dest = Request.getUser(userString, "getUser");
		
		InetAddress adr = dest.getAddress();
		
		//Récupération du TCPChat associé au dest
		for(TCPChat tcp : agent.getListeTCPChat()) {
			if(tcp.getSocket().getInetAddress().equals(adr)) {
				t=tcp;
			}
		}
		t.addPropertyChangeListener(this);
		
		this.frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		
		this.frame.setSize(new Dimension(400, 400));
		this.frame.setResizable(true);
		
		this.wa = new WindowAdapter() {
				public void windowClosing(WindowEvent e) {
					int quitter = FenetreMenu.fenetreFermeture();
					if(quitter == 0) {
						frame.dispose();
					}
		}};
		
		this.panel = new JPanel();
		this.panel.setOpaque(false);
		
		this.addWidgets();
		afficherHistorique();
		frame.getRootPane().setDefaultButton(envoyer);
		
		frame.addWindowListener(wa);
		frame.setVisible(true);
		
	}


	private void addWidgets() {
		
		Color c = new Color(25, 94, 125);
		
		JTextPane textPane = new JTextPane();
		textPane.setEditable(false);
		textPane.setOpaque(true);

        this.doc = textPane.getStyledDocument();
        
        SimpleAttributeSet right = new SimpleAttributeSet();
        StyleConstants.setAlignment(right, StyleConstants.ALIGN_RIGHT);
        StyleConstants.setForeground(right, Color.WHITE);
        
        SimpleAttributeSet left = new SimpleAttributeSet();
        StyleConstants.setAlignment(left, StyleConstants.ALIGN_LEFT);
        StyleConstants.setForeground(left, c.brighter());
		
		GridBagLayout gridBagLayout = new GridBagLayout();
		gridBagLayout.columnWidths = new int[]{394, 0};
		gridBagLayout.rowHeights = new int[]{16, 220, 74, 0};
		gridBagLayout.columnWeights = new double[]{0.0, Double.MIN_VALUE};
		gridBagLayout.rowWeights = new double[]{0.0, 0.0, 0.0, Double.MIN_VALUE};
		this.frame.getContentPane().setLayout(gridBagLayout);
		
		//zone pour entrer les message à envoyer
		text = new JTextArea(10, 3);
		text.setForeground(Color.WHITE);
		text.setBackground(Color.GRAY);
		text.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
		text.setFont(new Font("Century Schoolbook", Font.PLAIN, 12));
		text.setText("Enter your message");
		text.setOpaque(false);
		
		text.addKeyListener(new KeyListener() {
			public void keyPressed(KeyEvent e) {
				if (e.getKeyCode() == KeyEvent.VK_ENTER){
					e.consume();
				}
			}

			@Override
			public void keyTyped(KeyEvent e) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void keyReleased(KeyEvent e) {
				// TODO Auto-generated method stub
				
			}
		});
		
		JScrollPane sp = new JScrollPane(text);
		
		//zone affichage texte
		JScrollPane sp2 = new JScrollPane(textPane);
		new SmartScroller(sp2);
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.fill = GridBagConstraints.BOTH;
		gbc.insets = new Insets(0, 0, 5, 0);
		gbc.gridx = 0;
		gbc.gridy = 1;
		frame.getContentPane().add(sp2, gbc);
		
		//bouton envoyer
		envoyer = new JButton("Send");
		envoyer.setOpaque(false);
		frame.getRootPane().setDefaultButton(envoyer);
		envoyer.addActionListener(new ActionListener() {
			private Date date;
			public void actionPerformed(ActionEvent e) {
				
				//récupération du texte entré par le user
				String message = text.getText();
				
				//récupération id user et dest
				int idUser = agent.getDb().getIdFromPseudo(user.getPseudo());
				int idDest = agent.getDb().getIdFromPseudo(dest.getPseudo());
				
				//récupération du TCPChat associé au dest
				try {
					TCPChat tcpChat = null;
					for(TCPChat tcp : agent.getListeTCPChat()) {
						if (tcp.getDestID() == idDest) {
							tcpChat = tcp;
						}
					}
					
					text.setText("");
					
					//Création de la date du message
					this.setDate(new Date());
			        DateFormat format = new SimpleDateFormat(" (yyyy/MM/dd HH:mm:ss)");
			        String dateString = format.format(this.date);
			        
			        //Envoi du message
					tcpChat.sendMsg(message);
					
					//Affichage du message et de la date
					doc.insertString(doc.getLength(), "\n"+message+dateString, right );
		            doc.setParagraphAttributes(doc.getLength(), 1, right, false);
		            text.setCaretPosition(text.getDocument().getLength());
		            
		            //Si le chat entre user et dest existe déjà dans la base de donnée
					if(agent.getDb().tableChatExists(idUser, idDest)) {
						
						//ajout du message dans la table
						agent.getDb().addMessage(idUser, idDest, message);
						
					//Sinon
					}else {
						//Création de la table et ajout du message 
						agent.getDb().newChatTable(idUser, idDest);
						agent.getDb().addMessage(idUser, idDest, message);
					}
				} catch (IOException | BadLocationException e1) {
					System.out.println("Envoi du message impossible");
					e1.printStackTrace();
				}
			}
			public void setDate(Date d) {
				this.date=d;
			}
				
			});
		
		panel.add(BorderLayout.CENTER, sp);
		panel.add(BorderLayout.SOUTH,envoyer);
		panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
		
		GridBagConstraints gbc_panel = new GridBagConstraints();
		gbc_panel.anchor = GridBagConstraints.NORTH;
		gbc_panel.fill = GridBagConstraints.HORIZONTAL;
		gbc_panel.gridx = 0;
		gbc_panel.gridy = 2;
		frame.getContentPane().add(panel, gbc_panel);
	}


	public static JTextArea getTa() {
		return text;
	}


	public void setTa(JTextArea ta) {
		this.text = ta;
	}


	public static StyledDocument getDoc() {
		return doc;
	}


	public static void setDoc(StyledDocument doc) {
		FenetreChat.doc = doc;
	}
	
	public void afficherHistorique() {
		Color c = new Color(25, 94, 125);
		
		SimpleAttributeSet right = new SimpleAttributeSet();
        StyleConstants.setAlignment(right, StyleConstants.ALIGN_RIGHT);
        StyleConstants.setForeground(right, Color.WHITE);
        
        SimpleAttributeSet left = new SimpleAttributeSet();
        StyleConstants.setAlignment(left, StyleConstants.ALIGN_LEFT);
        StyleConstants.setForeground(left, c.brighter());
        
		int idUser = agent.getDb().getIdFromPseudo(user.getPseudo());
		int idDest = agent.getDb().getIdFromPseudo(dest.getPseudo());
		
		if(agent.getDb().tableChatExists(idUser, idDest)) {
			
			ArrayList<MessageAffichage> historic = null;
			try {
				historic = agent.getDb().getHistoric(idUser, idDest);
			} catch (SQLException e2) {
				e2.printStackTrace();
			}
			
			for(MessageAffichage msg : historic) {
				
				if(msg.getId() == idUser) {
					try {
						doc.insertString(doc.getLength(), "\n"+msg.getMessage(), right );
					} catch (BadLocationException e1) {
						e1.printStackTrace();
					}
		            doc.setParagraphAttributes(doc.getLength(), 1, right, false);
				}else {
					try {
						doc.insertString(doc.getLength(), "\n"+msg.getMessage(), left );
					} catch (BadLocationException e1) {
						e1.printStackTrace();
					}
					doc.setParagraphAttributes(doc.getLength(), 1, left, false);
				}
			}
		}
	}
	
	public void propertyChange(PropertyChangeEvent evt) {
		switch(evt.getPropertyName()){
			case "deconnexion" :
				InetAddress adr = dest.getAddress();
				TCPChat t=null;
				for(TCPChat tcp : agent.getListeTCPChat()) {
					if(tcp.getSocket().getInetAddress().equals(adr)) {
						t=tcp;
					}
				}
				try {
					t.getSocket().close();
				} catch (IOException e) {
					e.printStackTrace();
				}
				agent.getListeTCPChat().remove(t);
				agent.getListeTCPChat2().remove(t);
				break;
				
		}
	}
	
	public static boolean isOuvert() {
		return ouvert;
	}
	
	public static void fermer() {
		frame.dispose();
	}
	
	public static Contact getDest() {
		return dest;
	}
	
}
		
