package btdex.ui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;

import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.ListSelectionModel;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.html.HTMLDocument;

import org.apache.commons.text.StringEscapeUtils;

import btdex.core.Globals;
import jiconfont.icons.font_awesome.FontAwesome;
import jiconfont.swing.IconFontSwing;

public class ChatPanel extends JPanel implements ActionListener, ListSelectionListener {
	private static final long serialVersionUID = 144264934272036916L;
	
	private static final int MAX_LENGTH = 280;

	private static final String STYLE_SHEET =
            ".container-friend {\n" + 
            "  border: 2px solid #bbbbbb;\n" + 
			"  font-family: Dialog;\n" + 
            "  padding: 4px;\n" + 
            "  margin: 4px 0;\n" + 
            "}\n" + 
            ".container-you {\n" + 
			"  font-family: Dialog;\n" + 
            "  padding: 4px;\n" + 
            "  margin: 4px 0;\n" + 
            "  text-align: left;\n" + 
            "}\n" + 
            ".time {\n" + 
			"  font-family: Dialog;\n" + 
            "  font-size: small;\n" + 
            "}\n"
            ;
    private static final String HTML_FORMAT
            = "<style>" + STYLE_SHEET + "</style>"
               + "<div id=content> </div>"
            ;

    private static final String FRIEND_CHAT_FORMAT = "<div class=\"container-friend\">\n" + 
    		"  <div>%s</div>\n" + 
    		"  <div class=\"time\">BURST-XXXX-X 11:00</div>\n" + 
    		"</div>";
    private static final String YOU_CHAT_FORMAT = "<div class=\"container-you\">\n" + 
    		"  <div align=\"right\">%s</div>\n" + 
    		"  <div align=\"right\" class=\"time\">You 11:01</div>\n" + 
    		"</div>";

    private JTextField inputField;
    private JTextPane displayField;
    
    private JPasswordField pinField;
    private char []pin;

	private JList<String> addressList;

	private JButton btnSend;

	private JScrollPane scrollPane;

    public ChatPanel() {
    	super(new BorderLayout());

		JPanel addressPanel = new JPanel(new BorderLayout());
		addressPanel.setBorder(BorderFactory.createTitledBorder("Your contacts"));
		addressList = new JList<>();
		addressList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		addressList.setPreferredSize(new Dimension(300, 300));
		addressPanel.add(addressList, BorderLayout.CENTER);		
		add(addressPanel, BorderLayout.LINE_START);
		addressList.addListSelectionListener(this);
		
		pinField = new JPasswordField(12);
		pinField.addActionListener(this);

    	JPanel panelSendMessage = new JPanel(new BorderLayout());
        inputField = new JTextField();
        inputField.setToolTipText("Enter your message");
        panelSendMessage.add(new Desc("Enter your message", inputField), BorderLayout.CENTER);
        inputField.addActionListener(this);
        inputField.setEnabled(false);

        btnSend = new JButton("");
		Icon sendIcon = IconFontSwing.buildIcon(FontAwesome.PAPER_PLANE_O, 24, btnSend.getForeground());
        btnSend.setIcon(sendIcon);
        btnSend.setToolTipText("Send your message");
        btnSend.addActionListener(this);
        btnSend.setEnabled(false);
        panelSendMessage.add(new Desc(" ", btnSend), BorderLayout.EAST);

        displayField = new JTextPane();
        displayField.setContentType("text/html");
        displayField.setEditable(false);
        displayField.setText(HTML_FORMAT);

        scrollPane = new JScrollPane(displayField);
        scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        
        JPanel panelCenter = new JPanel(new BorderLayout());
        panelCenter.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
        add(panelCenter, BorderLayout.CENTER);
        
        panelCenter.add(scrollPane, BorderLayout.CENTER);
        panelCenter.add(panelSendMessage, BorderLayout.SOUTH);
        
        setSize(280, 400);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
    	if(e.getSource() == btnSend || e.getSource() == inputField) {
    		if(inputField.getText().length() == 0)
    			return;
    		if(inputField.getText().length() > MAX_LENGTH) {
				Toast.makeText(Main.getInstance(), "Maximum length of a message is " + MAX_LENGTH +
						" characters.", Toast.Style.ERROR).display(inputField);
				return;
    		}
    		appendMeMyMessage(inputField.getText());
    		inputField.setText("");
    		inputField.requestFocus();
    	}
    	if(e.getSource() == pinField) {
    		pin = pinField.getPassword();
    		if(!Globals.getInstance().checkPIN(pin)) {
				Toast.makeText(Main.getInstance(), "Invalid PIN", Toast.Style.ERROR).display(pinField);
				return;
    		}
    	}
    }

    private String prepareHtmlString(String rawContent) {
        return StringEscapeUtils.escapeXml10(rawContent);
    }

    private void appendRawHtmlChatContent(String html) {
        HTMLDocument document = (HTMLDocument) displayField.getDocument();
        Element contentElement = document.getElement("content");
        try {
            if (contentElement.getElementCount() > 0) {
                Element lastElement = contentElement.getElement(contentElement.getElementCount() - 1);
                document = (HTMLDocument) contentElement.getDocument();
                document.insertAfterEnd(lastElement, html);
            } else {
                document.insertAfterStart(contentElement, html);
            }
        } catch (BadLocationException | IOException ignored) {
        }
        
        SwingUtilities.invokeLater(() -> {
            JScrollBar bar = scrollPane.getVerticalScrollBar();
            if(bar!=null)
            	bar.setValue(bar.getMaximum());
        });
    }
    
    public void clearMessages() {
        displayField.setText(HTML_FORMAT);
    }

    public void appendFriendMessage(String message) {
        String htmlMessage = prepareHtmlString(message);
        appendRawHtmlChatContent(String.format(FRIEND_CHAT_FORMAT, htmlMessage));
    }

    public void appendMeMyMessage(String message) {
        String htmlMessage = prepareHtmlString(message);
        appendRawHtmlChatContent(String.format(YOU_CHAT_FORMAT, htmlMessage));
    }

    public static void main(String[] args) {
		IconFontSwing.register(FontAwesome.getIconFont());

		JFrame f = new JFrame("Chat test");
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		ChatPanel chat = new ChatPanel();
		f.getContentPane().add(chat);
		
		chat.appendFriendMessage("Message from friend");
		chat.appendMeMyMessage("Message from me");
		chat.appendFriendMessage("Another from friend");
		chat.appendMeMyMessage("Another from me, but this is a very long message, very very very long message");
		
		f.pack();
		f.setLocationRelativeTo(null);
		f.setVisible(true);
	}

	@Override
	public void valueChanged(ListSelectionEvent e) {
		
	}
}