/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.modules.tasklist.ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JToolBar;
import java.io.Serializable;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
import org.netbeans.modules.tasklist.filter.FilterRepository;
import org.netbeans.modules.tasklist.impl.ScannerList;
import org.netbeans.modules.tasklist.impl.ScanningScopeList;
import org.netbeans.modules.tasklist.impl.TaskList;
import org.netbeans.modules.tasklist.impl.TaskManagerImpl;
import org.netbeans.spi.tasklist.Task;
import org.netbeans.spi.tasklist.TaskScanningScope;
import org.openide.util.Cancellable;
import org.openide.util.HelpCtx;
import org.openide.util.ImageUtilities;
import org.openide.util.NbBundle;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;

/**
 * Top component which displays something.
 */
final class TaskListTopComponent extends TopComponent {
    
    private static TaskListTopComponent instance;
    /** path to the icon used by the component and its open action */
    static final String ICON_PATH = "org/netbeans/modules/tasklist/ui/resources/taskList.png"; //NOI18N
    
    private static final String PREFERRED_ID = "TaskListTopComponent"; //NOI18N
    
    private TaskManagerImpl taskManager;
    private PropertyChangeListener scopeListListener;
    private PropertyChangeListener scannerListListener;
    private TaskListModel model;
    private FilterRepository filters;
    private TaskListTable table;
    private PropertyChangeListener changeListener;
    private TaskList.Listener tasksListener;

    private static final boolean isMacLaf = "Aqua".equals(UIManager.getLookAndFeel().getID());
    private static final Color macBackground = UIManager.getColor("NbExplorerView.background");
    
    private TaskListTopComponent() {
        taskManager = TaskManagerImpl.getInstance();
        
        initComponents();
//        statusBarPanel.setMinimumSize(new JLabel("dummy").getPreferredSize());
        setName(NbBundle.getMessage(TaskListTopComponent.class, "CTL_TaskListTopComponent")); //NOI18N
        setToolTipText(NbBundle.getMessage(TaskListTopComponent.class, "HINT_TaskListTopComponent")); //NOI18N
        setIcon(ImageUtilities.loadImage(ICON_PATH, true));
        
        tableScroll.addMouseListener( new MouseAdapter() {
            @Override
            public void mousePressed( MouseEvent e ) {
                maybePopup( e );
            }
            
            @Override
            public void mouseReleased( MouseEvent e ) {
                maybePopup( e );
            }
        });
        if( isMacLaf ) {
            tableScroll.setBackground(macBackground);
            tableScroll.getViewport().setBackground(macBackground);
            toolbar.setBackground(macBackground);
            statusBarPanel.setBackground(macBackground);
        }

    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        toolbar = new javax.swing.JToolBar();
        tableHolderPanel = new javax.swing.JPanel();
        tableScroll = new javax.swing.JScrollPane();
        toolbarSeparator = new javax.swing.JSeparator();
        statusSeparator = new javax.swing.JSeparator();
        statusBarPanel = new javax.swing.JPanel();

        setLayout(new java.awt.GridBagLayout());

        toolbar.setFloatable(false);
        toolbar.setOrientation(javax.swing.SwingConstants.VERTICAL);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weighty = 1.0;
        add(toolbar, gridBagConstraints);

        tableHolderPanel.setOpaque(false);

        tableScroll.setBorder(null);

        javax.swing.GroupLayout tableHolderPanelLayout = new javax.swing.GroupLayout(tableHolderPanel);
        tableHolderPanel.setLayout(tableHolderPanelLayout);
        tableHolderPanelLayout.setHorizontalGroup(
            tableHolderPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(tableScroll, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 397, Short.MAX_VALUE)
        );
        tableHolderPanelLayout.setVerticalGroup(
            tableHolderPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(tableScroll, javax.swing.GroupLayout.DEFAULT_SIZE, 299, Short.MAX_VALUE)
        );

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        add(tableHolderPanel, gridBagConstraints);

        toolbarSeparator.setOrientation(javax.swing.SwingConstants.VERTICAL);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.weighty = 1.0;
        add(toolbarSeparator, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHWEST;
        gridBagConstraints.weightx = 1.0;
        add(statusSeparator, gridBagConstraints);

        statusBarPanel.setLayout(new java.awt.BorderLayout());
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTHEAST;
        gridBagConstraints.weightx = 1.0;
        add(statusBarPanel, gridBagConstraints);
    }// </editor-fold>//GEN-END:initComponents
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel statusBarPanel;
    private javax.swing.JSeparator statusSeparator;
    private javax.swing.JPanel tableHolderPanel;
    private javax.swing.JScrollPane tableScroll;
    private javax.swing.JToolBar toolbar;
    private javax.swing.JSeparator toolbarSeparator;
    // End of variables declaration//GEN-END:variables
    
    /**
     * Gets default instance. Do not use directly: reserved for *.settings files only,
     * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
     * To obtain the singleton instance, use {@link findInstance}.
     */
    public static synchronized TaskListTopComponent getDefault() {
        if (instance == null) {
            instance = new TaskListTopComponent();
        }
        return instance;
    }
    
    /**
     * Obtain the TaskListTopComponent instance. Never call {@link #getDefault} directly!
     */
    public static synchronized TaskListTopComponent findInstance() {
        TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
        if (win == null) {
            getLogger().log( Level.INFO, "Cannot find TaskList component. It will not be located properly in the window system." ); //NOI18N
            return getDefault();
        }
        if (win instanceof TaskListTopComponent) {
            return (TaskListTopComponent)win;
        }
        getLogger().log( Level.INFO,
                "There seem to be multiple components with the '" + PREFERRED_ID + //NOI18N
                "' ID. That is a potential source of errors and unexpected behavior."); //NOI18N
        return getDefault();
    }
    
    @Override
    public int getPersistenceType() {
        return TopComponent.PERSISTENCE_ALWAYS;
    }
    
    @Override
    public void componentOpened() {
        if( null == model ) {
            toolbarSeparator.setVisible(false);
            statusSeparator.setVisible(false);
            tableScroll.setViewportView( createNoTasksMessage() );
        }

        WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
            @Override
            public void run() {
                TaskManagerImpl.RP.post(new Runnable() {
                    @Override
                    public void run() {
                        init();
                    }
                });
            }
        });
    }
    
    private void init() {
        TaskScanningScope activeScope = getActiveScope();
        if( null == filters ) {
            try {
                filters = FilterRepository.getDefault();
                filters.load();
            } catch( IOException ioE ) {
                getLogger().log( Level.INFO, ioE.getMessage(), ioE );
            }
        }

        if( null == changeListener ) {
            changeListener = createChangeListener();
            taskManager.addPropertyChangeListener( TaskManagerImpl.PROP_WORKING_STATUS, changeListener );
        }
        
        if( null == model ) {
            table = new TaskListTable();
            if( isMacLaf )
                table.setBackground(macBackground);
            //later on the button in the toolbar will switch to the previously used table model
            model = new TaskListModel( taskManager.getTasks() );
            table.setModel( model );
            tasksListener = new TaskList.Listener() {
                @Override
                public void tasksAdded( List<? extends Task> tasks ) {
                    Runnable runnable = new Runnable() {
                        @Override
                        public void run() {
                            tableScroll.setViewportView( table );
                            Color background = UIManager.getColor("TextArea.background"); //NOI18N
                            if( null != background )
                                tableScroll.getViewport().setBackground( background );
                            tableScroll.setBorder( BorderFactory.createEmptyBorder() );
                            if( isMacLaf ) {
                                table.setBackground(macBackground);
                                tableScroll.getViewport().setBackground(macBackground);
                            }
                        }
                    };
                    taskManager.getTasks().removeListener(tasksListener);
                    if( SwingUtilities.isEventDispatchThread() ) {
                        runnable.run();
                    } else {
                        SwingUtilities.invokeLater(runnable);
                    }
                    tasksListener = null;
                }

                @Override
                public void tasksRemoved(List<? extends Task> tasks) {
                }

                @Override
                public void cleared() {
                }
            };
            taskManager.getTasks().addListener(tasksListener);
            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {
                    tableScroll.setViewportView( createNoTasksMessage() );
                    tableScroll.setBorder( BorderFactory.createEmptyBorder() );
                    
                    statusBarPanel.add( new CountStatusBar(taskManager.getTasks()), BorderLayout.WEST );
                    statusBarPanel.add( new ScopeStatusBar(taskManager), BorderLayout.CENTER );

                    toolbarSeparator.setVisible(true);
                    statusSeparator.setVisible(true);
                    rebuildToolbar();
                }
            });
        }
        SwingUtilities.invokeLater( new Runnable() {
            @Override
            public void run() {
                ScanningScopeList.getDefault().addPropertyChangeListener( getScopeListListener() );
                ScannerList.getFileScannerList().addPropertyChangeListener( getScannerListListener() );
                ScannerList.getPushScannerList().addPropertyChangeListener( getScannerListListener() );
            }
        });
        
        final TaskScanningScope scopeToObserve = activeScope;
        taskManager.observe( scopeToObserve, filters.getActive() );
    }

    private Component createNoTasksMessage() {
        JPanel panel = new JPanel( new BorderLayout() );
        if( isMacLaf ) {
            panel.setBackground(macBackground);
        } else {
            Color background = UIManager.getColor("TextArea.background"); //NOI18N
            if( null != background )
                panel.setBackground( background );
        }
        JLabel msg = new JLabel( NbBundle.getMessage(TaskListTopComponent.class, "LBL_NoTasks" ) ); //NOI18N
        msg.setHorizontalAlignment(JLabel.CENTER);
        msg.setEnabled(false);
        msg.setOpaque(false);
        panel.add( msg, BorderLayout.CENTER );
        return panel;
    }
    
    @Override
    public void componentClosed() {
        ScanningScopeList.getDefault().removePropertyChangeListener( getScopeListListener() );
        ScannerList.getFileScannerList().removePropertyChangeListener( getScannerListListener() );
        ScannerList.getPushScannerList().removePropertyChangeListener( getScannerListListener() );
        taskManager.observe( null, null );
        if( null != changeListener ) {
            taskManager.removePropertyChangeListener( TaskManagerImpl.PROP_WORKING_STATUS, changeListener );
            changeListener = null;
        }
        synchronized( this ) {
            if( null != progress )
                progress.finish();
            progress = null;
        }
        try {
            FilterRepository.getDefault().save();
        } catch( IOException ioE ) {
            getLogger().log( Level.INFO, null, ioE );
        }
    }
    
    @Override
    public void requestActive() {
        super.requestActive();
        if( null != table )
            table.requestFocusInWindow();
    }
    
    @Override
    public Object writeReplace() {
        return new ResolvableHelper();
    }
    
    @Override
    protected String preferredID() {
        return PREFERRED_ID;
    }
    
    private void maybePopup( MouseEvent e ) {
        if( e.isPopupTrigger() && null != table ) {
            e.consume();
            JPopupMenu popup = Util.createPopup( table );
            popup.show( this, e.getX(), e.getY() );
        }
    }
    
    private PropertyChangeListener getScopeListListener() {
        if( null == scopeListListener ) {
            scopeListListener = new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent arg0) {
                    ScanningScopeList scopeList = ScanningScopeList.getDefault();
                    List<TaskScanningScope> newScopes = scopeList.getTaskScanningScopes();
                    if( newScopes.isEmpty() ) {
                        getLogger().log( Level.INFO, "No task scanning scope found" ); //NOI18N
                    }
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            rebuildToolbar();
                        }
                    });
                }
            };
        }
        return scopeListListener;
    }
    
    private PropertyChangeListener getScannerListListener() {
        if( null == scannerListListener ) {
            scannerListListener = new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent e) {
                    final TaskScanningScope scopeToObserve = taskManager.getScope();
                    taskManager.observe( null, null );
                    SwingUtilities.invokeLater( new Runnable() {
                        @Override
                        public void run() {
                            taskManager.observe( scopeToObserve, filters.getActive() );
                        }
                    });
                }
            };
        }
        return scannerListListener;
    }
    
    private void rebuildToolbar() {
        toolbar.removeAll();
        toolbar.setFocusable( false );
        //scope buttons
        List<TaskScanningScope> scopes = ScanningScopeList.getDefault().getTaskScanningScopes();
        for( TaskScanningScope scope : scopes ) {
            final ScopeButton scopeButton = new ScopeButton( taskManager, scope );
            scopeButton.setSelected(scope.equals(Settings.getDefault().getActiveScanningScope()));
            toolbar.add(scopeButton);
        }
        toolbar.add( new JToolBar.Separator() );
        //filter
        JToggleButton toggleFilter = new FiltersMenuButton( filters.getActive() );
        toolbar.add( toggleFilter );
        //grouping & other butons
        toolbar.addSeparator();
        final JToggleButton toggleGroups = new JToggleButton( ImageUtilities.loadImageIcon("org/netbeans/modules/tasklist/ui/resources/groups.png", false)); //NOI18N
        toggleGroups.addItemListener( new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                switchTableModel( e.getStateChange() == ItemEvent.SELECTED );
                Settings.getDefault().setGroupTasksByCategory( toggleGroups.isSelected() );
                toggleGroups.setToolTipText( toggleGroups.isSelected() 
                        ? NbBundle.getMessage( TaskListTopComponent.class, "HINT_TasksAsList" )  //NOI18N
                        : NbBundle.getMessage( TaskListTopComponent.class, "HINT_GrouppedTasks" ) ); //NOI18N
            }
        });
        toggleGroups.setSelected( Settings.getDefault().getGroupTasksByCategory() );
        toggleGroups.setToolTipText( toggleGroups.isSelected() 
                        ? NbBundle.getMessage( TaskListTopComponent.class, "HINT_TasksAsList" )  //NOI18N
                        : NbBundle.getMessage( TaskListTopComponent.class, "HINT_GrouppedTasks" ) ); //NOI18N
        toggleGroups.setFocusable( false );
        toolbar.add( toggleGroups );
    }
    
    private void switchTableModel( boolean useFoldingModel ) {
        if( useFoldingModel ) {
            model = new FoldingTaskListModel( taskManager.getTasks() );
            table.setModel( model );
            statusBarPanel.removeAll();
        } else {
            model = new TaskListModel( taskManager.getTasks() );
            table.setModel( model );
            statusBarPanel.add( new CountStatusBar(taskManager.getTasks()), BorderLayout.WEST );
            statusBarPanel.add( new ScopeStatusBar(taskManager), BorderLayout.CENTER );
        }
        statusBarPanel.setVisible( !useFoldingModel );
        statusSeparator.setVisible( !useFoldingModel );
    }
    
    static private Logger getLogger() {
        return Logger.getLogger( TaskListTopComponent.class.getName() );
    }

    private ProgressHandle progress;
    private PropertyChangeListener createChangeListener() {
        return new PropertyChangeListener() {
            @Override
            public void propertyChange( PropertyChangeEvent e ) {
                synchronized( TaskListTopComponent.this ) {
                    if( ((Boolean)e.getNewValue()).booleanValue() ) {
                        if( null == progress ) {
                            progress = ProgressHandleFactory.createHandle(
                                    NbBundle.getMessage( TaskListTopComponent.class, "LBL_ScanProgress" ), //NOI18N
                                    new Cancellable() { //NOI18N
                                        @Override
                                        public boolean cancel() {
                                            taskManager.abort();
                                            return true;
                                        }
                                    });
                            progress.start();
                            progress.switchToIndeterminate();
                        }
                    } else {
                        if( null != progress )
                            progress.finish();
                        progress = null;
                    }
                }
            }
        };
    }
    
    final static class ResolvableHelper implements Serializable {
        private static final long serialVersionUID = 1L;
        public Object readResolve() {
            return TaskListTopComponent.getDefault();
        }
    }
    
   /** Defines task list Help ID */
    @Override
    public HelpCtx getHelpCtx () {
        return new HelpCtx(TaskListTopComponent.class);
    }

    private TaskScanningScope getActiveScope() {
        TaskScanningScope activeScope = Settings.getDefault().getActiveScanningScope();
        if( null == activeScope )
            activeScope = ScanningScopeList.getDefault().getDefaultScope();
        return activeScope;
    }
}
