package org.apache.catalina.tribes.demos;

import java.io.Serializable;
import java.util.Map;

import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;

import org.apache.catalina.tribes.Channel;
import org.apache.catalina.tribes.ChannelListener;
import org.apache.catalina.tribes.ManagedChannel;
import org.apache.catalina.tribes.Member;
import org.apache.catalina.tribes.MembershipListener;
import org.apache.catalina.tribes.tipis.AbstractReplicatedMap;
import org.apache.catalina.tribes.tipis.LazyReplicatedMap;
import javax.swing.table.DefaultTableCellRenderer;
import java.awt.Color;
import java.awt.Component;
import javax.swing.table.TableColumn;
import org.apache.catalina.tribes.util.UUIDGenerator;
import org.apache.catalina.tribes.util.Arrays;

/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2005</p>
 *
 * <p>Company: </p>
 *
 * @author not attributable
 * @version 1.0
 */
public class MapDemo implements ChannelListener, MembershipListener{
    
    protected LazyReplicatedMap map;
    protected SimpleTableDemo table;
    
    public MapDemo(Channel channel, String mapName ) {
        map = new LazyReplicatedMap(null,channel,5000, mapName,null);
        table = SimpleTableDemo.createAndShowGUI(map,channel.getLocalMember(false).getName());
        channel.addChannelListener(this);
        channel.addMembershipListener(this);
//        for ( int i=0; i<1000; i++ ) {
//            map.put("MyKey-"+i,"My String Value-"+i);
//        }
        this.messageReceived(null,null);
    }
    
    public boolean accept(Serializable msg, Member source) {
        table.dataModel.getValueAt(-1,-1);
        return false;
    }
    
    public void messageReceived(Serializable msg, Member source) {
        
    }
    
    public void memberAdded(Member member) {
    }
    public void memberDisappeared(Member member) {
        table.dataModel.getValueAt(-1,-1);
    }
    
    public static void usage() {
        System.out.println("Tribes MapDemo.");
        System.out.println("Usage:\n\t" + 
                           "java MapDemo [channel options] mapName\n\t" +
                           "\tChannel options:" +
                           ChannelCreator.usage());
    }

    public static void main(String[] args) throws Exception {
        long start = System.currentTimeMillis();
        ManagedChannel channel = (ManagedChannel) ChannelCreator.createChannel(args);
        String mapName = "MapDemo";
        if ( args.length > 0 && (!args[args.length-1].startsWith("-"))) {
            mapName = args[args.length-1];
        }
        channel.start(channel.DEFAULT);
        Runtime.getRuntime().addShutdownHook(new Shutdown(channel));
        MapDemo demo = new MapDemo(channel,mapName);
        
        System.out.println("System test complete, time to start="+(System.currentTimeMillis()-start)+" ms. Sleeping to let threads finish.");
        Thread.sleep(60 * 1000 * 60);
    }

    public static class Shutdown
        extends Thread {
        ManagedChannel channel = null;
        public Shutdown(ManagedChannel channel) {
            this.channel = channel;
        }

        public void run() {
            System.out.println("Shutting down...");
            SystemExit exit = new SystemExit(5000);
            exit.setDaemon(true);
            exit.start();
            try {
                channel.stop(channel.DEFAULT);

            } catch (Exception x) {
                x.printStackTrace();
            }
            System.out.println("Channel stopped.");
        }
    }

    public static class SystemExit
        extends Thread {
        private long delay;
        public SystemExit(long delay) {
            this.delay = delay;
        }

        public void run() {
            try {
                Thread.sleep(delay);
            } catch (Exception x) {
                x.printStackTrace();
            }
            System.exit(0);

        }
    }

    public static class SimpleTableDemo
        extends JPanel implements ActionListener{
        private static int WIDTH = 550;
        
        private LazyReplicatedMap map;
        private boolean DEBUG = false;
        AbstractTableModel dataModel = new AbstractTableModel() {
            
            
            String[] columnNames = {
                                   "Key",
                                   "Value",
                                   "Backup Node",
                                   "isPrimary",
                                   "isProxy",
                                   "isBackup"};

            public int getColumnCount() { return columnNames.length; }
    
            public int getRowCount() {return map.sizeFull() +1; }
            
            public StringBuffer getMemberNames(Member[] members){
                StringBuffer buf = new StringBuffer();
                if ( members!=null ) {
                    for (int i=0;i<members.length; i++ ) {
                        buf.append(members[i].getName());
                        buf.append("; ");
                    }
                }
                return buf;
            }
            
            public Object getValueAt(int row, int col) {
                if ( row==-1 ) {
                    update();
                    return "";
                }
                if ( row == 0 ) return columnNames[col];
                Object[] entries = map.entrySetFull().toArray();
                Map.Entry e = (Map.Entry)entries [row-1];
                LazyReplicatedMap.MapEntry entry = (LazyReplicatedMap.MapEntry)e.getValue();
                switch (col) {
                    case 0: return entry.getKey();
                    case 1: return entry.getValue();
                    case 2: return getMemberNames(entry.getBackupNodes());
                    case 3: return new Boolean(entry.isPrimary());
                    case 4: return new Boolean(entry.isProxy());
                    case 5: return new Boolean(entry.isBackup());
                    default: return "";
                }
                
            }
            
            public void update() {
                fireTableDataChanged();
            }
        };
        
        JTextField txtAddKey = new JTextField(20);
        JTextField txtAddValue = new JTextField(20);
        JTextField txtRemoveKey = new JTextField(20);
        JTextField txtChangeKey = new JTextField(20);
        JTextField txtChangeValue = new JTextField(20);
        
        JTable table = null;
        public SimpleTableDemo(LazyReplicatedMap map) {
            super();
            this.map = map;
            
            this.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);

            //final JTable table = new JTable(data, columnNames);
            table = new JTable(dataModel);

            table.setPreferredScrollableViewportSize(new Dimension(WIDTH, 150));
            for ( int i=0; i<table.getColumnCount(); i++ ) {
                TableColumn tm = table.getColumnModel().getColumn(i);
                tm.setCellRenderer(new ColorRenderer());
            }


            if (DEBUG) {
                table.addMouseListener(new MouseAdapter() {
                    public void mouseClicked(MouseEvent e) {
                        printDebugData(table);
                    }
                });
            }
            
            //setLayout(new GridLayout(5, 0));
            setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

            //Create the scroll pane and add the table to it.
            JScrollPane scrollPane = new JScrollPane(table);

            //Add the scroll pane to this panel.
            add(scrollPane);
            
            //create a add value button
            JPanel addpanel = new JPanel();
            addpanel.setPreferredSize(new Dimension(WIDTH,30));
            addpanel.add(createButton("Add","add"));
            addpanel.add(txtAddKey);
            addpanel.add(txtAddValue);
            addpanel.setMaximumSize(new Dimension(WIDTH,30));
            add(addpanel);
            
            //create a remove value button
            JPanel removepanel = new JPanel( );
            removepanel.setPreferredSize(new Dimension(WIDTH,30));
            removepanel.add(createButton("Remove","remove"));
            removepanel.add(txtRemoveKey);
            removepanel.setMaximumSize(new Dimension(WIDTH,30));
            add(removepanel);

            //create a change value button
            JPanel changepanel = new JPanel( );
            changepanel.add(createButton("Change","change"));
            changepanel.add(txtChangeKey);
            changepanel.add(txtChangeValue);
            changepanel.setPreferredSize(new Dimension(WIDTH,30));
            changepanel.setMaximumSize(new Dimension(WIDTH,30));
            add(changepanel);


            //create sync button
            JPanel syncpanel = new JPanel( );
            syncpanel.add(createButton("Synchronize","sync"));
            syncpanel.add(createButton("Replicate","replicate"));
            syncpanel.add(createButton("Random","random"));
            syncpanel.setPreferredSize(new Dimension(WIDTH,30));
            syncpanel.setMaximumSize(new Dimension(WIDTH,30));
            add(syncpanel);


        }
        
        public JButton createButton(String text, String command) {
            JButton button = new JButton(text);
            button.setActionCommand(command);
            button.addActionListener(this);
            return button;
        }
        
        public void actionPerformed(ActionEvent e) {
            System.out.println(e.getActionCommand());
            if ( "add".equals(e.getActionCommand()) ) {
                System.out.println("Add key:"+txtAddKey.getText()+" value:"+txtAddValue.getText());
                map.put(txtAddKey.getText(),new StringBuffer(txtAddValue.getText()));
            }
            if ( "change".equals(e.getActionCommand()) ) {
                System.out.println("Change key:"+txtChangeKey.getText()+" value:"+txtChangeValue.getText());
                StringBuffer buf = (StringBuffer)map.get(txtChangeKey.getText());
                if ( buf!=null ) {
                    buf.delete(0,buf.length());
                    buf.append(txtChangeValue.getText());
                    map.replicate(txtChangeKey.getText(),true);
                } else {
                    buf = new StringBuffer();
                    buf.append(txtChangeValue.getText());
                    map.put(txtChangeKey.getText(),buf);
                }
            }
            if ( "remove".equals(e.getActionCommand()) ) {
                System.out.println("Remove key:"+txtRemoveKey.getText());
                map.remove(txtRemoveKey.getText());
            }
            if ( "sync".equals(e.getActionCommand()) ) {
                System.out.println("Syncing from another node.");
                map.transferState();
            }
            if ( "random".equals(e.getActionCommand()) ) {
                Thread t = new Thread() {
                    public void run() {
                        for (int i = 0; i < 100; i++) {
                            String key = Arrays.toString(UUIDGenerator.randomUUID(false));
                            map.put(key, key);
                            dataModel.fireTableDataChanged();
                            table.paint(table.getGraphics());
                            try {
                                Thread.sleep(500);
                            } catch (InterruptedException x) {
                                Thread.currentThread().interrupted();
                            }
                        }
                    }
                };
                t.start();
            }
            
            if ( "replicate".equals(e.getActionCommand()) ) {
                System.out.println("Replicating out to the other nodes.");
                map.replicate(true);
            }
            dataModel.getValueAt(-1,-1);
        }

        private void printDebugData(JTable table) {
            int numRows = table.getRowCount();
            int numCols = table.getColumnCount();
            javax.swing.table.TableModel model = table.getModel();

            System.out.println("Value of data: ");
            for (int i = 0; i < numRows; i++) {
                System.out.print("    row " + i + ":");
                for (int j = 0; j < numCols; j++) {
                    System.out.print("  " + model.getValueAt(i, j));
                }
                System.out.println();
            }
            System.out.println("--------------------------");
        }

        /**
         * Create the GUI and show it.  For thread safety,
         * this method should be invoked from the
         * event-dispatching thread.
         */
        public static SimpleTableDemo createAndShowGUI(LazyReplicatedMap map, String title) {
            //Make sure we have nice window decorations.
            JFrame.setDefaultLookAndFeelDecorated(true);

            //Create and set up the window.
            JFrame frame = new JFrame("SimpleTableDemo - "+title);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            //Create and set up the content pane.
            SimpleTableDemo newContentPane = new SimpleTableDemo(map);
            newContentPane.setOpaque(true); //content panes must be opaque
            frame.setContentPane(newContentPane);

            //Display the window.
            frame.setSize(450,250);
            newContentPane.setSize(450,300);
            frame.pack();
            frame.setVisible(true);
            return newContentPane;
        }
    }
    
    static class ColorRenderer extends DefaultTableCellRenderer {
        
        public ColorRenderer() {
            super();
        }

        public Component getTableCellRendererComponent
            (JTable table, Object value, boolean isSelected,
             boolean hasFocus, int row, int column) {
            Component cell = super.getTableCellRendererComponent
                             (table, value, isSelected, hasFocus, row, column);
            cell.setBackground(Color.WHITE);
            if ( row > 0 ) {
                Color color = null;
                boolean primary = ( (Boolean) table.getValueAt(row, 3)).booleanValue();
                boolean proxy = ( (Boolean) table.getValueAt(row, 4)).booleanValue();
                boolean backup = ( (Boolean) table.getValueAt(row, 5)).booleanValue();
                if (primary) color = Color.GREEN;
                else if (proxy) color = Color.RED;
                else if (backup) color = Color.BLUE;
                if ( color != null ) cell.setBackground(color);
            }
//            System.out.println("Row:"+row+" Column:"+column+" Color:"+cell.getBackground());
//            cell.setBackground(bkgndColor);
//            cell.setForeground(fgndColor);

            return cell;
        }
        
        
    }


}
