package com.dlsc.flexgantt.showcase.demo.lazyloading;

import java.awt.BorderLayout;
import java.awt.GridLayout;

import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.TreePath;

import com.dlsc.flexgantt.command.IProgressMonitor;
import com.dlsc.flexgantt.showcase.AbstractDemo;
import com.dlsc.flexgantt.showcase.DemoControlsPanel;
import com.dlsc.flexgantt.model.gantt.DefaultGanttChartModel;
import com.dlsc.flexgantt.model.gantt.DefaultGanttChartNode;
import com.dlsc.flexgantt.model.treetable.DefaultColumnModel;
import com.dlsc.flexgantt.model.treetable.TreeTableColumn;
import com.dlsc.flexgantt.swing.GanttChart;
import com.dlsc.flexgantt.swing.GanttChartFrame;
import com.dlsc.flexgantt.swing.treetable.TreeTable;
import com.dlsc.flexgantt.swing.util.AbstractSwingWorker;

public class LazyLoadingDemo extends AbstractDemo implements
        TreeWillExpandListener {

    private GanttChart gc;
    private JRadioButton modal;
    private JRadioButton nonModal;
    private JRadioButton infinite;

    public LazyLoadingDemo() {
        super("Lazy Loading");
    }

    @Override
    public String[] getSourceCodeFileNames() {
        return new String[] { "LazyLoadingDemo" };
    }

    @SuppressWarnings("unchecked")
    @Override
    public void run(boolean embedded) {
        DefaultGanttChartNode root = new DefaultGanttChartNode();
        root.setKey("Root");
        root.setColumnValue(Boolean.FALSE, 0);
        root.setColumnValue(10, 1);

        DefaultGanttChartModel model = new DefaultGanttChartModel(root, true);

        gc = createGanttChart(model);
        gc.getTreeTable().setCreationEnabled(true);

        TreeTable table = gc.getTreeTable();
        table.setCreationEnabled(false);
        table.addTreeWillExpandListener(this);
        table.collapseAll();

        DefaultColumnModel colModel = (DefaultColumnModel) gc.getColumnModel();
        colModel.getKeyColumn().setWidth(200);

        TreeTableColumn loadedColumn = new TreeTableColumn<String>("Loaded",
                Boolean.class, 0);
        loadedColumn.setWidth(50);
        colModel.addColumn(loadedColumn);

        TreeTableColumn countColumn = new TreeTableColumn<String>("Children",
                Integer.class, 1);
        countColumn.setWidth(50);
        colModel.addColumn(countColumn);
        gc.resetToPreferredSizes();

        GanttChartFrame<?> frame = createFrame("Lazy Loading", gc, embedded);

        JPanel controls = new DemoControlsPanel(this);
        controls.setLayout(new BorderLayout());

        JPanel group = new JPanel();
        group.setBorder(createTitledBorder("Progress Bar Location"));
        group.setLayout(new GridLayout(3, 1));

        modal = new JRadioButton("Dialog");
        nonModal = new JRadioButton("Status Bar");
        infinite = new JRadioButton("Infinite");

        ButtonGroup bg = new ButtonGroup();
        bg.add(modal);
        bg.add(nonModal);
        bg.add(infinite);

        modal.setSelected(true);

        group.add(modal);
        group.add(nonModal);
        group.add(infinite);

        controls.add(BorderLayout.NORTH, group);
        frame.add(BorderLayout.EAST, controls);

        if (embedded) {
            frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        } else {
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }
        frame.center();
        frame.setVisible(true);
    }

    @Override
    public void treeWillCollapse(TreeExpansionEvent event)
            throws ExpandVetoException {
    }

    @Override
    public void treeWillExpand(final TreeExpansionEvent event)
            throws ExpandVetoException {
        AbstractSwingWorker worker = new AbstractSwingWorker() {
            @Override
            public Object construct() {
                GanttChartFrame<?> frame = (GanttChartFrame<?>) getFrame();
                frame.showBusy();

                // modal
                IProgressMonitor monitor = gc.getProgressMonitorFactory()
                        .createProgressMonitor();
                if (nonModal.isSelected()) {
                    monitor = (IProgressMonitor) frame.getStatusBar();
                } else if (infinite.isSelected()) {
                    monitor = (IProgressMonitor) frame.getGlassPane();
                }

                TreePath path = event.getPath();
                DefaultGanttChartNode node = (DefaultGanttChartNode) path
                        .getLastPathComponent();
                Object value = node.getColumnValue(0);
                if (value == null || value.equals(Boolean.FALSE)) {
                    int count = (Integer) node.getColumnValue(1);
                    monitor.beginTask("Accessing a simulated database...",
                            count);
                    for (int i = 0; i < count; i++) {
                        if (!monitor.isCanceled()) {
                            monitor.worked(1);
                            DefaultGanttChartNode child = new DefaultGanttChartNode();
                            child.setKey("Node " + (i + 1));
                            monitor.subTask("Loading node "
                                    + (String) child.getKey());
                            try {
                                Thread.sleep(333);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            child.setColumnValue(Boolean.FALSE, 0);
                            child.setColumnValue((int) (Math.random() * 25), 1);
                            node.add(child);
                        }
                        node.setColumnValue(node.getChildCount(), 1);
                    }
                    node.setColumnValue(Boolean.TRUE, 0);
                }

                monitor.done();
                return null;
            }

            @Override
            public void finished() {
                TreePath path = event.getPath();
                TreeTable table = (TreeTable) event.getSource();
                GanttChartFrame<?> frame = (GanttChartFrame<?>) getFrame();
                frame.showReady();
                table.expandPathAnimated(path);
            }
        };

        DefaultGanttChartNode node = (DefaultGanttChartNode) event.getPath()
                .getLastPathComponent();
        if (!((Boolean) node.getColumnValue(0))) {
            worker.start();
            throw new ExpandVetoException(event);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new LazyLoadingDemo());
    }
}
