package org.apache.log4j.chainsaw.zeroconf;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.jmdns.JmDNS;
import javax.jmdns.ServiceEvent;
import javax.jmdns.ServiceInfo;
import javax.jmdns.ServiceListener;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JToolBar;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.chainsaw.ModifiableListModel;
import org.apache.log4j.chainsaw.SmallButton;
import org.apache.log4j.chainsaw.help.HelpManager;
import org.apache.log4j.chainsaw.icons.ChainsawIcons;
import org.apache.log4j.chainsaw.plugins.GUIPluginSkeleton;
import org.apache.log4j.chainsaw.prefs.SettingsManager;
import org.apache.log4j.net.SocketHubReceiver;
import org.apache.log4j.net.ZeroConfSocketHubAppender;
import org.apache.log4j.net.Zeroconf4log4j;
import org.apache.log4j.plugins.Plugin;
import org.apache.log4j.plugins.PluginEvent;
import org.apache.log4j.plugins.PluginListener;
import org.apache.log4j.spi.LoggerRepositoryEx;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * This plugin is designed to detect specific Zeroconf zones (Rendevouz/Bonjour,
 * whatever people are calling it) and allow the user to double click on
 * 'devices' to try and connect to them with no configuration needed.
 * 
 * TODO add autoConnect visuals, and save it in a model 
 * TODO need to handle
 * NON-log4j devices that may be broadcast in the interested zones 
 * TODO add the
 * default Zone, and the list of user-specified zones to a preferenceModel
 * 
 * To run this in trial mode, first run {@link ZeroConfSocketHubAppenderTestBed}, then
 * run this class' main(..) method.
 * 
 * @author psmith
 * 
 */
public class ZeroConfPlugin extends GUIPluginSkeleton {

    private static final Logger LOG = Logger.getLogger(ZeroConfPlugin.class);

    private static final Icon DEVICE_DISCOVERED_ICON = new ImageIcon(ChainsawIcons.ANIM_RADIO_TOWER);

    private ModifiableListModel discoveredDevices = new ModifiableListModel();

    private final JList listBox = new JList(discoveredDevices);

    private final JScrollPane scrollPane = new JScrollPane(listBox);

    private JmDNS jmDNS;

    private ZeroConfPreferenceModel preferenceModel;
    
    private Map serviceInfoToReceiveMap = new HashMap();

    private JMenu connectToMenu = new JMenu("Connect to");
    private JMenuItem helpItem = new JMenuItem(new AbstractAction("Learn more about ZeroConf...",
            ChainsawIcons.ICON_HELP) {

        public void actionPerformed(ActionEvent e) {
            HelpManager.getInstance()
                    .showHelpForClass(ZeroConfPlugin.class);
        }
    });  
    
    private JMenuItem nothingToConnectTo = new JMenuItem("No devices discovered");
    
    public ZeroConfPlugin() {
        setName("Zeroconf");
    }

    public void shutdown() {
        Zeroconf4log4j.shutdown();
        save();
    }

    private void save() {
        File fileLocation = getPreferenceFileLocation();
        XStream stream = new XStream(new DomDriver());
        try {
            stream.toXML(preferenceModel, new FileWriter(fileLocation));
        } catch (Exception e) {
            LOG.error("Failed to save ZeroConfPlugin configuration file",e);
        }
    }

    private File getPreferenceFileLocation() {
        return new File(SettingsManager.getInstance().getSettingsDirectory(), "zeroconfprefs.xml");
    }

    public void activateOptions() {
        setLayout(new BorderLayout());
        jmDNS = Zeroconf4log4j.getInstance();

        jmDNS.addServiceListener(
                ZeroConfSocketHubAppender.DEFAULT_ZEROCONF_ZONE,
                new ZeroConfServiceListener());

        listBox.setCellRenderer(new ServiceInfoListCellRenderer());
        listBox.setLayoutOrientation(JList.HORIZONTAL_WRAP);
        listBox.setFixedCellHeight(75);
        listBox.setFixedCellWidth(200);
        listBox.setVisibleRowCount(-1);
        listBox.addMouseListener(new ConnectorMouseListener());
        JToolBar toolbar = new JToolBar();
        SmallButton helpButton = new SmallButton(helpItem.getAction());
        helpButton.setText(helpItem.getText());
        toolbar.add(helpButton);
        toolbar.setFloatable(false);
        add(toolbar, BorderLayout.NORTH);
        add(scrollPane, BorderLayout.CENTER);
        
        injectMenu();
        
        ((LoggerRepositoryEx)LogManager.getLoggerRepository()).getPluginRegistry().addPluginListener(new PluginListener() {

            public void pluginStarted(PluginEvent e) {
                
            }

            public void pluginStopped(PluginEvent e) {
                Plugin plugin = e.getPlugin();
                synchronized(serviceInfoToReceiveMap) {
                    for (Iterator iter = serviceInfoToReceiveMap.entrySet().iterator(); iter.hasNext();) {
                        Map.Entry entry = (Map.Entry) iter.next();
                        if(entry.getValue() == plugin) {
                            serviceInfoToReceiveMap.remove(entry.getKey());
                        }
                    }
                }
//                 need to make sure that the menu item tracking this item has it's icon and enabled state updade
                JMenuItem item = locateMatchingMenuItem(plugin.getName());
                if (item!=null) {
                    item.setEnabled(true);
                    item.setIcon(null);
                }
                discoveredDevices.fireContentsChanged();
            }});

        File fileLocation = getPreferenceFileLocation();
        XStream stream = new XStream(new DomDriver());
        if (fileLocation.exists()) {
            try {
                this.preferenceModel = (ZeroConfPreferenceModel) stream
                        .fromXML(new FileReader(fileLocation));
            } catch (Exception e) {
                LOG.error("Failed to load ZeroConfPlugin configuration file",e);
            }
        }else {
            this.preferenceModel = new ZeroConfPreferenceModel();
        }
        
        discoveredDevices.addListDataListener(new ListDataListener() {

            public void intervalAdded(ListDataEvent e) {
                setIconIfNeeded();
            }

            public void intervalRemoved(ListDataEvent e) {
                setIconIfNeeded();
            }

            public void contentsChanged(ListDataEvent e) {
                setIconIfNeeded();
            }});
    }
    
    /**
     * Sets the icon of this parent container (a JTabbedPane, we hope
     *
     */
    private void setIconIfNeeded() {
        Container container = this.getParent();
        if(container instanceof JTabbedPane) {
            JTabbedPane tabbedPane = (JTabbedPane) container;
            Icon icon = discoveredDevices.getSize()==0?null:DEVICE_DISCOVERED_ICON;
            tabbedPane.setIconAt(tabbedPane.indexOfTab(getName()), icon);
        }else {
            LOG.warn("Parent is not a TabbedPane, not setting icon: " + container.getClass().getName());
        }
    }

    /**
     * Attempts to find a JFrame container as a parent,and addse a "Connect to" menu
     *
     */
    private void injectMenu() {
        
        JFrame frame = (JFrame) SwingUtilities.getWindowAncestor(this);
        if(frame == null) {
            LOG.info("Could not locate parent JFrame to add menu to");
        }else {
            JMenuBar menuBar = frame.getJMenuBar();
            if(menuBar==null ) {
                menuBar = new JMenuBar();
                frame.setJMenuBar(menuBar);
            }
            insertToLeftOfHelp(menuBar, connectToMenu);
            connectToMenu.add(nothingToConnectTo);
            
            discoveredDevices.addListDataListener(new ListDataListener() {

                public void intervalAdded(ListDataEvent e) {
                    if(discoveredDevices.getSize()>0) {
                        connectToMenu.remove(nothingToConnectTo);
                    }
                }

                public void intervalRemoved(ListDataEvent e) {
                    if(discoveredDevices.getSize()==0) {
                        connectToMenu.add(nothingToConnectTo,0);
                    }
                    
                }

                public void contentsChanged(ListDataEvent e) {
                }});
            
            nothingToConnectTo.setEnabled(false);

            connectToMenu.addSeparator();
            connectToMenu.add(helpItem);
        }
    }

    private void insertToLeftOfHelp(JMenuBar menuBar, JMenu item) {
        for (int i = 0; i < menuBar.getMenuCount(); i++) {
            JMenu menu = menuBar.getMenu(i);
            if(menu.getText().equalsIgnoreCase("help")) {
                menuBar.add(item, i-1);
            }
        }
        LOG.warn("menu '" + item.getText() + "' was NOT added because the 'Help' menu could not be located");
    }

    private void deviceDiscovered(final ServiceInfo info) {
        final String name = info.getName();
//        TODO currently adding ALL devices to autoConnectlist
//        preferenceModel.addAutoConnectDevice(name);
        
        
        JMenuItem connectToDeviceMenuItem = new JMenuItem(new AbstractAction(info.getName()) {

            public void actionPerformed(ActionEvent e) {
                connectTo(info);
            }});
        
        if(discoveredDevices.getSize()>0) {
            for (int i = 0; i < discoveredDevices.getSize(); i++) {
                if (name.compareToIgnoreCase(((ServiceInfo) discoveredDevices
                        .elementAt(i)).getName()) < 0) {
                    discoveredDevices.insertElementAt(info, i);
                }
            }
            Component[] menuComponents = connectToMenu.getMenuComponents();
            boolean located = false;
            for (int i = 0; i < menuComponents.length; i++) {
                Component c = menuComponents[i];
                if (!(c instanceof JPopupMenu.Separator)) {
                    JMenuItem item = (JMenuItem) menuComponents[i];
                    if (item.getText().compareToIgnoreCase(name) < 0) {
                        connectToMenu.insert(connectToDeviceMenuItem, i);
                        located = true;
                        break;
                    }
                }
            }
            if(!located) {
                connectToMenu.insert(connectToDeviceMenuItem,0);
            }
        }else {
            discoveredDevices.addElement(info);
            connectToMenu.insert(connectToDeviceMenuItem,0);
        }
//         if the device name is one of the autoconnect devices, then connect immediately
        if (preferenceModel.getAutoConnectDevices().contains(name)) {
            new Thread(new Runnable() {

                public void run() {
                    LOG.info("Auto-connecting to " + name);
                    connectTo(info);
                }
            }).start();
        }
    }
    
    private void deviceRemoved(String name) {
        for (int i = 0; i < discoveredDevices.getSize(); i++) {
            if (name.compareToIgnoreCase(((ServiceInfo) discoveredDevices
                    .elementAt(i)).getName()) == 0) {
                discoveredDevices.remove(i);
            }
        }
        Component[] menuComponents = connectToMenu.getMenuComponents();
        for (int i = 0; i < menuComponents.length; i++) {
            Component c = menuComponents[i];
            if (!(c instanceof JPopupMenu.Separator)) {
                JMenuItem item = (JMenuItem) menuComponents[i];
                if (item.getText().compareToIgnoreCase(name) == 0) {
                    connectToMenu.remove(item);
                    break;
                }
            }
        }
    }
        
    private class ZeroConfServiceListener implements ServiceListener {

        public void serviceAdded(final ServiceEvent event) {
            LOG.info("Service Added: " + event);
            /**
             * it's not very clear whether we should do the resolving in a
             * background thread or not.. All it says is to NOT do it in the AWT
             * thread, so I'm thinking it probably should be a background thread
             */
            Runnable runnable = new Runnable() {
                public void run() {
                    ZeroConfPlugin.this.jmDNS.requestServiceInfo(event
                            .getType(), event.getName());
                }
            };
            Thread thread = new Thread(runnable,
                    "ChainsawZeroConfRequestResolutionThread");
            thread.setPriority(Thread.MIN_PRIORITY);
            thread.start();
        }

        public void serviceRemoved(ServiceEvent event) {
            LOG.info("Service Removed: " + event);
            deviceRemoved(event.getName());
        }

        public void serviceResolved(ServiceEvent event) {
            LOG.info("Service Resolved: " + event);
            deviceDiscovered(event.getInfo());
        }

    }

    private class ServiceInfoListCellRenderer implements
            ListCellRenderer {

        private JPanel panel = new JPanel(new BorderLayout(15, 15));

        private final ImageIcon ICON = new ImageIcon(
                ChainsawIcons.ANIM_RADIO_TOWER);
        
        private JLabel iconLabel = new JLabel(ICON);

        private JLabel nameLabel = new JLabel();

        private JLabel detailLabel = new JLabel();

        private JCheckBox autoConnect = new JCheckBox();

        private Box southBox = Box.createVerticalBox();
        private JCheckBox checkBox = new JCheckBox();
        
        private ServiceInfoListCellRenderer() {
            Font font = nameLabel.getFont();
            font = font.deriveFont(font.getSize() + 6);
            nameLabel.setFont(font);
            panel.setLayout(new BorderLayout());
            panel.add(iconLabel, BorderLayout.WEST);

            JPanel centerPanel = new JPanel(new BorderLayout(3, 3));

            centerPanel.add(nameLabel, BorderLayout.CENTER);
            centerPanel.add(southBox, BorderLayout.SOUTH);
            panel.add(centerPanel, BorderLayout.CENTER);
            
            southBox.add(detailLabel);
            Box hBox = Box.createHorizontalBox();
            hBox.add(Box.createHorizontalGlue());
            hBox.add(new JLabel("Auto-connect:"));
            hBox.add(checkBox);

            southBox.add(hBox);
            
            panel.setBorder(BorderFactory.createEtchedBorder());
        }

        public Component getListCellRendererComponent(JList list, Object value,
                int index, boolean isSelected, boolean cellHasFocus) {
            if (isSelected) {
                panel.setBackground(list.getSelectionBackground());
                panel.setForeground(list.getSelectionForeground());
            } else {
                panel.setBackground(list.getBackground());
                panel.setForeground(list.getForeground());
            }
            ServiceInfo info = (ServiceInfo) value;
            nameLabel.setText(info.getName());
            detailLabel.setText(info.getHostAddress() + ":" + info.getPort());
            iconLabel.setIcon(isConnectedTo(info)?ICON:null);
            checkBox.setSelected(preferenceModel.getAutoConnectDevices().contains(info.getName()));
            return panel;
        }

    }

    private class ConnectorMouseListener extends MouseAdapter {

        public void mouseClicked(MouseEvent e) {
            if (e.getClickCount() == 2) {
                int index = listBox.locationToIndex(e.getPoint());
                ListModel dlm = discoveredDevices;
                ServiceInfo info = (ServiceInfo) dlm.getElementAt(index);
                listBox.ensureIndexIsVisible(index);
                if (!isConnectedTo(info)) {
                    connectTo(info);
                } else {
                    disconnectFrom(info);
                }
            }
        }

        public void mousePressed(MouseEvent e) {
            /**
             * This methodh handles when the user clicks the
             * auto-connect
             */
            int index = listBox.locationToIndex(e.getPoint());

            if (index != -1) {
//                Point p = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), )
                Component c = SwingUtilities.getDeepestComponentAt(ZeroConfPlugin.this, e.getX(), e.getY());
                if (c instanceof JCheckBox) {
                    ServiceInfo info = (ServiceInfo) listBox.getModel()
                            .getElementAt(index);
                    String name = info.getName();
                    if (preferenceModel.getAutoConnectDevices().contains(name)) {
                        preferenceModel.removeAutoConnectDevice(name);
                    } else {
                        preferenceModel.addAutoConnectDevice(name);
                    }
                    discoveredDevices.fireContentsChanged();
                    repaint();
                }
            }
        }
    }

    private void disconnectFrom(ServiceInfo info) {
        if(!isConnectedTo(info)) {
            return; // not connected, who cares
        }
        Plugin plugin;
        synchronized (serviceInfoToReceiveMap) {
            plugin = (Plugin) serviceInfoToReceiveMap.get(info);
        }
        ((LoggerRepositoryEx)LogManager.getLoggerRepository()).getPluginRegistry().stopPlugin(plugin.getName());
    }
    /**
     * returns true if the serviceInfo record already has a matching connected receiver
     * @param info
     * @return
     */
    private boolean isConnectedTo(ServiceInfo info) {
        return serviceInfoToReceiveMap.containsKey(info);
    }
    /**
     * Starts a receiver to the appender referenced within the ServiceInfo
     * @param info
     */
    private void connectTo(ServiceInfo info) {
        LOG.info("Connection request for " + info);
        int port = info.getPort();
        String hostAddress = info.getHostAddress();
       
//        TODO handle different receivers than just SocketHubReceiver
        SocketHubReceiver receiver = new SocketHubReceiver();
        receiver.setHost(hostAddress);
        receiver.setPort(port);
        receiver.setName(info.getName());
        
        ((LoggerRepositoryEx)LogManager.getLoggerRepository()).getPluginRegistry().addPlugin(receiver);
        receiver.activateOptions();
        LOG.info("Receiver '" + receiver.getName() + "' has been started");
        
        // ServiceInfo obeys equals() and hashCode() contracts, so this should be safe.
        synchronized (serviceInfoToReceiveMap) {
            serviceInfoToReceiveMap.put(info, receiver);
        }
        
//         this instance of the menu item needs to be disabled, and have an icon added
        JMenuItem item = locateMatchingMenuItem(info.getName());
        if (item!=null) {
            item.setIcon(new ImageIcon(ChainsawIcons.ANIM_NET_CONNECT));
            item.setEnabled(false);
        }
        // now notify the list model has changed, it needs redrawing of the receiver icon now it's connected
        discoveredDevices.fireContentsChanged();
    }

    /**
     * Finds the matching JMenuItem based on name, may return null if there is no match.
     * 
     * @param name
     * @return
     */
    private JMenuItem locateMatchingMenuItem(String name) {
        Component[] menuComponents = connectToMenu.getMenuComponents();
        for (int i = 0; i < menuComponents.length; i++) {
            Component c = menuComponents[i];
            if (!(c instanceof JPopupMenu.Separator)) {
                JMenuItem item = (JMenuItem) menuComponents[i];
                if (item.getText().compareToIgnoreCase(name) == 0) {
                    return item;
                }
            }
        }
        return null;
    }

    public static void main(String[] args) throws InterruptedException {

        BasicConfigurator.resetConfiguration();
        BasicConfigurator.configure();

        final ZeroConfPlugin plugin = new ZeroConfPlugin();


        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.getContentPane().setLayout(new BorderLayout());
        frame.getContentPane().add(plugin, BorderLayout.CENTER);

        // needs to be activated after being added to the JFrame for Menu injection to work
        plugin.activateOptions();

        frame.pack();
        frame.setVisible(true);

        Thread thread = new Thread(new Runnable() {
            public void run() {
                plugin.shutdown();
            }
        });
        Runtime.getRuntime().addShutdownHook(thread);
    }

}
