package com.glitchcog.fontificator.gui.chat;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JRootPane;
import javax.swing.KeyStroke;

import com.glitchcog.fontificator.config.ConfigChat;
import com.glitchcog.fontificator.config.FontificatorProperties;
import com.glitchcog.fontificator.gui.FontificatorError;
import com.glitchcog.fontificator.gui.controls.ControlWindow;

/**
 * This window displays the chat. It is intended to be minimalistic and solely display the chat.
 * 
 * @author Matt Yanos
 */
public class ChatWindow extends JFrame
{
    private static final long serialVersionUID = 1L;

    /**
     * A stored reference to the chat panel, used whenever some part of the system has a reference to this ChatWindow,
     * but needs to modify something on the panel. This is in lieu of putting a bunch of accessor methods here to do
     * pass through the function to the panel in an encapsulated way.
     */
    private ChatPanel chatPanel;

    /**
     * A static copy of this ChatWindow for accessing it globally
     */
    public static ChatWindow me;

    /**
     * The popup for submitting errors that the user needs to see
     */
    public static FontificatorError popup;

    /**
     * Mouse listeners for dragging the Chat Window around when dragging the mouse inside the chat
     */
    private ChatMouseListeners mouseListeners;

    /**
     * Escape stroke to close popups
     */
    private static final KeyStroke escapeStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);

    /**
     * Construct the Chat Window
     */
    public ChatWindow()
    {
        me = this;
        setTitle("Fontificator Chat");
        popup = new FontificatorError(null);
    }

    /**
     * Sets the properties to get hooks into the properties' configuration models; Sets the ControlWindow to get hooks
     * back into the controls; Sets the loaded member Boolean to indicate it has everything it needs to begin rendering
     * the visualization
     * 
     * @param fProps
     * @param ctrlWindow
     * @throws IOException
     */
    public void initChat(final FontificatorProperties fProps, final ControlWindow ctrlWindow) throws IOException
    {
        chatPanel = new ChatPanel();
        add(chatPanel);

        mouseListeners = new ChatMouseListeners(this, ctrlWindow);
        addMouseListener(mouseListeners);
        addMouseMotionListener(mouseListeners);
        addMouseWheelListener(chatPanel);
        setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

        setChatSize(fProps.getChatConfig());

        setResizable(fProps.getChatConfig().isResizable());
        setAlwaysOnTop(fProps.getChatConfig().isAlwaysOnTop());

        chatPanel.setConfig(fProps);
        chatPanel.initExpirationTimer();

        addWindowListener(new WindowListener()
        {
            @Override
            public void windowOpened(WindowEvent e)
            {
            }

            @Override
            public void windowClosing(WindowEvent e)
            {
                callExit(e.getComponent());
            }

            @Override
            public void windowClosed(WindowEvent e)
            {
            }

            @Override
            public void windowIconified(WindowEvent e)
            {
            }

            @Override
            public void windowDeiconified(WindowEvent e)
            {
            }

            @Override
            public void windowActivated(WindowEvent e)
            {
            }

            @Override
            public void windowDeactivated(WindowEvent e)
            {
            }

            /**
             * Calls exit from the control window
             */
            private void callExit(Component caller)
            {
                ctrlWindow.attemptToExit(caller);
            }
        });

    }

    /**
     * Handles sizing the Chat Window, clearing out old JFrame-based config values in the ConfigChat model if they were
     * the only ones available
     * 
     * @param chatConfig
     */
    public void setChatSize(ConfigChat chatConfig)
    {
        if (chatConfig.getWindowWidth() != null && chatConfig.getWindowHeight() != null)
        {
            setSize(chatConfig.getWindowWidth(), chatConfig.getWindowHeight());
            chatConfig.setWidth(getContentPane().getWidth());
            chatConfig.setHeight(getContentPane().getHeight());
            chatConfig.clearLegacyWindowSize();
        }
        else if (chatConfig.getWidth() > 0 && chatConfig.getHeight() > 0)
        {
            getContentPane().setPreferredSize(new Dimension(chatConfig.getWidth(), chatConfig.getHeight()));
            getContentPane().setSize(chatConfig.getWidth(), chatConfig.getHeight());
            pack();
        }
    }

    /**
     * Does the work required to make the parameter JDialog be hidden when pressing escape
     * 
     * @param popup
     */
    public static void setupHideOnEscape(final JDialog popup)
    {
        Action aa = new AbstractAction()
        {
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent event)
            {
                popup.setVisible(false);
            }
        };
        final String mapKey = "escapePressed";
        JRootPane root = popup.getRootPane();
        root.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(escapeStroke, mapKey);
        root.getActionMap().put(mapKey, aa);
    }

    /**
     * Access to the chat panel through this window, for any places there is a reference to just the ChatWindow, but
     * that needs to affect the ChatPanel, which has all the actual chat options
     * 
     * @return chatPanel
     */
    public ChatPanel getChatPanel()
    {
        return chatPanel;
    }

    /**
     * This is a small hack to expose the ctrl window to the message control panel so its username case map can be
     * cleared out if the user changes the type of username case resolution
     */
    public void clearUsernameCases()
    {
        mouseListeners.clearUsernameCases();
    }

}
