/*
 * Copyright (c) 2002-2007 TeamDev Ltd. All rights reserved.
 *
 * Use is subject to license terms.
 *
 * The complete licence text can be found at
 * http://www.teamdev.com/winpack/license.jsf
 */
package com.jniwrapper.win32.samples.demo;

import com.jniwrapper.samples.shell.components.HTMLText;
import com.jniwrapper.samples.shell.components.LazyPanel;
import com.jniwrapper.samples.shell.components.LineBevel;
import com.jniwrapper.win32.hook.*;
import com.jniwrapper.win32.ui.Wnd;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.MessageFormat;

public class HooksSample extends LazyPanel
{
    private static final String VIRTUAL_KEY_CODE_PATTERN = "Virtual Key Code = {0}, Scan Code = {1}, Extended Key = {2}";
    private static final String COORDINATES_PATTERN = "Mouse Coordinates: X={0}, Y={1}";
    private static final String HOOK_NOT_INSTALLED_MESSAGE = "Hook is not installed.";
    private static final String HOOK_INSTALLED_MESSAGE = "Hook installed successfully.";

    private JLabel lblAdvisoryText;

    private JLabel lblMouseHook;
    private JLabel lblMouseHookHint;
    private JLabel lblMouseHookData;
    private JButton _installMouseHook;
    private JButton _uninstallMouseHook;
    private Hook _mouseHook;

    private JLabel lblKeyboarHook;
    private JLabel lblKeyboarHookHint;
    private JLabel lblKeyboarHookData;
    private JButton _installKeyboardHook;
    private JButton _uninstallKeyboardHook;
    private Hook _keyboardHook;
    private boolean _activated = false;

    public HooksSample(Window parent)
    {
        super(parent);
    }

    public void initialize() throws Exception
    {
        lblAdvisoryText = new HTMLText("The page demonstrates the WinPack ability to install Windows Hooks, using the Hooks API.");

        _mouseHook = Hook.MOUSE;
        _mouseHook.addListener(new HookEventListener()
        {
            public void onHookEvent(HookEventObject event)
            {
                MouseEvent mouseEvent = (MouseEvent)event;
                final com.jniwrapper.win32.Point point = mouseEvent.getPoint();
                lblMouseHookData.setText(getCoordinatesText(point.getX(), point.getY()));
            }
        });

        _keyboardHook = Hook.KEYBOARD;
        _keyboardHook.addListener(new HookEventListener()
        {
            public void onHookEvent(HookEventObject event)
            {
                KeyboardEvent keyboardEvent = (KeyboardEvent)event;
                lblKeyboarHookData.setText(getVirtualKeyCodeText(keyboardEvent.getVirtualKeyCode(),
                        keyboardEvent.getScanCode(),
                        keyboardEvent.isExtendedKey()));
            }
        });

        Dimension prefferedSize = new Dimension(8020);
        lblMouseHook = new JLabel("Mouse Hook");
        lblMouseHookHint = new HTMLText("This hook allows to intercept <u>all</u> mouse events.<br>Press the \"Install\" button to install the Mouse Hook and the \"Uninstall\" button to uninstall it.");
        lblMouseHookData = new JLabel(HOOK_NOT_INSTALLED_MESSAGE);
        _installMouseHook = new JButton("Install");
        _installMouseHook.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                if (!_mouseHook.isInstalled())
                {
                    _mouseHook.install();
                    lblMouseHookData.setText(HOOK_INSTALLED_MESSAGE);
                    _installMouseHook.setEnabled(false);
                    _uninstallMouseHook.setEnabled(true);
                }
            }
        });

        _installMouseHook.setPreferredSize(prefferedSize);
        _uninstallMouseHook = new JButton("Uninstall");
        _uninstallMouseHook.setEnabled(false);
        _uninstallMouseHook.setPreferredSize(prefferedSize);
        _uninstallMouseHook.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                uninstallMouseHook();
            }
        });

        lblKeyboarHook = new JLabel("Keyboard Hook");
        lblKeyboarHookHint = new HTMLText("This hook allows to intercept <u>all</u> keyboard events. Try typing some text in other window to see hook in action in Demo window." +
                "<br>Press the \"Install\" button to install the Keyboard Hook and the \"Uninstall\" button to uninstall it.");
        lblKeyboarHookData = new JLabel(HOOK_NOT_INSTALLED_MESSAGE);
        _installKeyboardHook = new JButton("Install");
        _installKeyboardHook.setPreferredSize(prefferedSize);
        _installKeyboardHook.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                if (!_keyboardHook.isInstalled())
                {
                    _keyboardHook.install();
                    lblKeyboarHookData.setText(HOOK_INSTALLED_MESSAGE);
                    _installKeyboardHook.setEnabled(false);
                    _uninstallKeyboardHook.setEnabled(true);
                }
            }
        });
        _uninstallKeyboardHook = new JButton("Uninstall");
        _uninstallKeyboardHook.setEnabled(false);
        _uninstallKeyboardHook.setPreferredSize(prefferedSize);
        _uninstallKeyboardHook.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                uninstallKeyboardHook();
            }
        });

        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable()
        {
            public void run()
            {
                if (_mouseHook.isInstalled())
                    _mouseHook.uninstall();

                if (_keyboardHook.isInstalled())
                    _keyboardHook.uninstall();
            }
        }));

        setLayout(new GridBagLayout());

        add(lblAdvisoryText, new GridBagConstraints(00210.00.0
                , GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(10101010)00));

        add(lblMouseHook, new GridBagConstraints(01110.00.0
                , GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(01000)00));

        JPanel bevel1 = new LineBevel();

        add(bevel1, new GridBagConstraints(11110.00.0
                , GridBagConstraints.EAST, GridBagConstraints.HORIZONTAL, new Insets(00010)00));

        add(lblMouseHookHint, new GridBagConstraints(02210.00.0
                , GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(010010)00));

        add(lblMouseHookData, new GridBagConstraints(03210.00.0
                , GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10101010)00));

        JPanel panel1 = new JPanel(new FlowLayout(FlowLayout.CENTER));

        panel1.add(_installMouseHook);
        panel1.add(_uninstallMouseHook);

        add(panel1, new GridBagConstraints(04210.00.0
                , GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL , new Insets(50100)00));

        add(lblKeyboarHook, new GridBagConstraints(05110.00.0
                , GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(01000)00));

        JPanel bevel2 = new LineBevel();

        add(bevel2, new GridBagConstraints(15110.00.0
                , GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(00010)00));

        add(lblKeyboarHookHint, new GridBagConstraints(06210.00.0
                , GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(010010)00));

        add(lblKeyboarHookData, new GridBagConstraints(07210.00.0
                , GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10101010)00));

        JPanel panel2 = new JPanel(new FlowLayout(FlowLayout.CENTER));

        panel2.add(_installKeyboardHook);
        panel2.add(_uninstallKeyboardHook);

        add(panel2, new GridBagConstraints(08210.00.0
                , GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(100100)00));

        add(new JPanel()new GridBagConstraints(09211.01.0
                , GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0000)00));

        super.initialize();
    }

    private void uninstallKeyboardHook()
    {
        if (_keyboardHook.isInstalled())
        {
            _keyboardHook.uninstall();
            lblKeyboarHookData.setText(HOOK_NOT_INSTALLED_MESSAGE);
            _installKeyboardHook.setEnabled(true);
            _uninstallKeyboardHook.setEnabled(false);
        }
    }

    private void uninstallMouseHook()
    {
        if (_mouseHook.isInstalled())
        {
            _mouseHook.uninstall();
            lblMouseHookData.setText(HOOK_NOT_INSTALLED_MESSAGE);
            _installMouseHook.setEnabled(true);
            _uninstallMouseHook.setEnabled(false);
        }
    }

    public void deactivate()
    {
        uninstallMouseHook();
        uninstallKeyboardHook();

        if (_activated)
        {
            Wnd parentWindow = new Wnd(getParentWindow());
            parentWindow.setTopmost(false);

            _activated = false;
        }

        super.deactivate();
    }

    private String getCoordinatesText(long x, long y)
    {
        return MessageFormat.format(COORDINATES_PATTERN, new Object[]{new Long(x)new Long(y)});
    }

    private String getVirtualKeyCodeText(long code, long scanCode, boolean extendedKey)
    {
        return MessageFormat.format(VIRTUAL_KEY_CODE_PATTERN,
                new Object[]{
                    new Long(code),
                    new Long(scanCode),
                    new Boolean(extendedKey),
                });
    }

    public void activate() throws Exception
    {
        super.activate();

        Wnd parentWindow = new Wnd(getParentWindow());
        parentWindow.setTopmost(true);

        _activated = true;
    }
}