/*
 * TV-Browser
 * Copyright (C) 04-2003 Martin Oberhauser (darras@users.sourcceforge.net)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * CVS information:
 *  $RCSfile$
 *   $Source$
 *     $Date: 2014-06-16 14:57:55 +0200 (Mo, 16 Jun 2014) $
 *   $Author: ds10 $
 * $Revision: 8137 $
 */

package tvbrowser.ui.settings;

import java.awt.Cursor;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;

import tvbrowser.core.ChannelList;
import tvbrowser.core.DummyChannel;
import tvbrowser.core.PluginAndDataServiceComparator;
import tvbrowser.core.PluginLoader;
import tvbrowser.core.Settings;
import tvbrowser.core.icontheme.IconLoader;

import tvbrowser.core.plugin.PluginProxy;
import tvbrowser.core.plugin.PluginProxyManager;
import tvbrowser.core.tvdataservice.TvDataServiceProxy;
import tvbrowser.core.tvdataservice.TvDataServiceProxyManager;
import tvbrowser.extras.common.InternalPluginProxyIf;
import tvbrowser.extras.common.InternalPluginProxyList;
import tvbrowser.ui.mainframe.MainFrame;
import tvbrowser.ui.update.SoftwareUpdateDlg;
import tvbrowser.ui.update.SoftwareUpdateDlg.FilterItem;

import util.browserlauncher.Launch;
import util.exc.ErrorHandler;
import util.exc.TvBrowserException;
import util.ui.Localizer;
import util.ui.TVBrowserIcons;
import util.ui.UiUtilities;

import com.jgoodies.forms.builder.ButtonBarBuilder;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

import devplugin.ActionMenu;
import devplugin.Channel;
import devplugin.InfoIf;

import devplugin.PluginInfo;

/**
 * This Tab shows the Plugin-Manager.
 * 
 * @author Martin Oberhauser
 */

public class PluginSettingsTab implements devplugin.SettingsTab, TableModelListener {
  /** Localizer */
  private static final util.ui.Localizer mLocalizer = util.ui.Localizer.getLocalizerFor(PluginSettingsTab.class);
  /** Logger */
  private static final Logger mLog = Logger.getLogger(PluginSettingsTab.class.getName());
  /** List of Plugins */
  private JTable mTable;
  /** Buttons of Panel */
  private JButton mInfo, mRemove;
  /** ListModel with Plugins */
  private DefaultTableModel mTableModel;
  /** SettingsDialog */
  private SettingsDialog mSettingsDialog;
  /** The auto update check box */
  private JCheckBox mAutoUpdates;
  private JButton mConfigure;
  private JComboBox mFilterBox;
  
  private ArrayList<Object> mPluginList;

  /**
   * Creates an instance of this class.
   * 
   * @param settingsDialog The TV-Browser settings dialog.
   */
  public PluginSettingsTab(SettingsDialog settingsDialog) {
    mSettingsDialog = settingsDialog;
  }

  public JPanel createSettingsPanel() {

    JPanel contentPanel = new JPanel(new FormLayout("default:grow, default", "default, 2dlu, default, 3dlu, fill:default:grow, 3dlu, default"));
    contentPanel.setBorder(Borders.DLU4);
    
    CellConstraints cc = new CellConstraints();
    
    JButton update = new JButton(mLocalizer.msg("updateInstallPlugin", "Update/Install Plugins"), IconLoader.getInstance().getIconFromTheme("actions", "web-search", 16));
    
    update.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        MainFrame.getInstance().showUpdatePluginsDlg(false);
      }
    });

    contentPanel.add(update, cc.xy(2,1));
    
    mAutoUpdates = new JCheckBox(mLocalizer.msg("autoUpdates","Find plugin updates automatically"), Settings.propAutoUpdatePlugins.getBoolean());
    mAutoUpdates.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {
        Settings.propAutoUpdatePlugins.setBoolean(e.getStateChange() == ItemEvent.SELECTED);
      }
    });

    contentPanel.add(mAutoUpdates, cc.xy(1,1));
    
    JPanel categorySelection = new JPanel(new FormLayout("default,3dlu,default:grow","default"));
    
    JLabel filterLabel = new JLabel(SoftwareUpdateDlg.mLocalizer.msg("filterLabel","Show only Plugins with the following category:"));
    mFilterBox = new JComboBox();
    mFilterBox.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent e) {
        populatePluginList();
      }
    });

    categorySelection.add(filterLabel, cc.xy(1,1));
    categorySelection.add(mFilterBox, cc.xy(3,1));
    
    contentPanel.add(categorySelection,cc.xyw(1,3,2));
    
    mTableModel = new DefaultTableModel() {
      public boolean isCellEditable(int row, int column) {
        if (column == 0) {
          Object value = getValueAt(row,1);
          
          if(value instanceof PluginProxy) {
            return !Settings.propBlockedPluginArray.isBlocked(((PluginProxy)value));
          }
        }
        
        return false;
      }

      @Override
      public Class<?> getColumnClass(int columnIndex) {
        if (columnIndex == 0) {
          return Boolean.class;
        }
        return super.getColumnClass(columnIndex);
      }
      
    };
    mTableModel.setColumnCount(2);
    mTableModel.setColumnIdentifiers(new String[] {mLocalizer.msg("active","Active"),mLocalizer.msg("plugin","Plugin")});

    mTable = new JTable(mTableModel);
    mTable.getTableHeader().setReorderingAllowed(false);
    mTable.getTableHeader().setResizingAllowed(false);
    mTable.getColumnModel().getColumn(0).setCellRenderer(PluginTableCellRenderer.getInstance());
    mTable.getColumnModel().getColumn(1).setCellRenderer(PluginTableCellRenderer.getInstance());
    mTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    mTable.setRowHeight(40);
    mTable.setShowVerticalLines(false);
    mTable.setShowHorizontalLines(false);
    mTable.getModel().addTableModelListener(this);

    int columnWidth = UiUtilities.getStringWidth(mTable.getFont(),mTableModel.getColumnName(0)) + 16;
    mTable.getColumnModel().getColumn(0).setPreferredWidth(columnWidth);
    mTable.getColumnModel().getColumn(0).setMaxWidth(columnWidth);

    mTable.addMouseListener(new MouseAdapter() {

       public void mousePressed(MouseEvent e) {
        if (e.isPopupTrigger()) {
          int rowIndex = mTable.rowAtPoint(e.getPoint());
          if (rowIndex >=0) {
            mTable.setRowSelectionInterval(rowIndex, rowIndex);
            Object plugin = mTable.getModel().getValueAt(rowIndex, 1);
            JPopupMenu menu;
            
            if(plugin instanceof InfoIf) {
              menu = createContextMenu((InfoIf)plugin);
            }
            else {
              menu = createContextMenu((InternalPluginProxyIf)plugin);
            }
            
            menu.show(mTable, e.getX(),  e.getY());
          }
        }
      }

      public void mouseReleased(MouseEvent e) {
        if (e.isPopupTrigger()) {
          int rowIndex = mTable.rowAtPoint(e.getPoint());
          if (rowIndex >=0) {
            mTable.setRowSelectionInterval(rowIndex, rowIndex);
            Object plugin = mTable.getModel().getValueAt(rowIndex, 1);
            JPopupMenu menu;
            
            if(plugin instanceof InfoIf) {
              menu = createContextMenu((InfoIf)plugin);
            }
            else {
              menu = createContextMenu((InternalPluginProxyIf)plugin);
            }
            
            menu.show(mTable, e.getX(),  e.getY());
          }
        }
      }
       
      public void mouseClicked(MouseEvent e) {
        if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) {
          int rowIndex = mTable.getSelectedRow();
           if (rowIndex >= 0) {
             Object proxy = mTableModel.getValueAt(rowIndex, 1);
             if (proxy instanceof PluginProxy) {
               showInfoDialog((PluginProxy) proxy);
             }
             else if (proxy instanceof InternalPluginProxyIf) {
               showInfoDialog((InternalPluginProxyIf)proxy);
             }
             else if (proxy instanceof TvDataServiceProxy) {
               showInformation((TvDataServiceProxy)proxy);
             }
           }
        }
      }
    });

    populatePluginList();
    
    JScrollPane pane = new JScrollPane(mTable);
    pane.getViewport().setBackground(mTable.getBackground());
    
    contentPanel.add(pane, cc.xyw(1,5,2));
    
    ButtonBarBuilder builder = new ButtonBarBuilder();

    mInfo = new JButton(mLocalizer.msg("info","Info"), IconLoader.getInstance().getIconFromTheme("status", "dialog-information", 16));
    mInfo.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        Object selection = getSelection();
        
        if(selection instanceof PluginProxy) {
          showInfoDialog((PluginProxy)selection);
        }
        else if (selection instanceof InternalPluginProxyIf) {
          showInfoDialog((InternalPluginProxyIf)selection);
        }
        else if (selection instanceof TvDataServiceProxy) {
          showInformation((TvDataServiceProxy)selection);
        }
      }
    });
    
    mConfigure = new JButton(mLocalizer.msg("configure", "Configure"), TVBrowserIcons.preferences(TVBrowserIcons.SIZE_SMALL));
    mConfigure.addActionListener(new ActionListener() {

      public void actionPerformed(ActionEvent e) {
        Object selection = getSelection();
        
        if(selection instanceof PluginProxy) {
          configurePlugin((PluginProxy)selection);
        }
        else if (selection instanceof InternalPluginProxyIf) {
          mSettingsDialog.showSettingsTab(((InternalPluginProxyIf) selection)
              .getSettingsId());
        }
        else if (selection instanceof TvDataServiceProxy) {
          configureService((TvDataServiceProxy)selection);
        }
      }
    });
    
    builder.addButton(mInfo);
    builder.addRelatedGap();
    builder.addButton(mConfigure);
    builder.addRelatedGap();
    builder.addGlue();
    builder.addRelatedGap();
    
    mRemove = new JButton(Localizer.getLocalization(Localizer.I18N_DELETE),TVBrowserIcons.delete(TVBrowserIcons.SIZE_SMALL));
    mRemove.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        if(getSelection() instanceof PluginProxy) {
          removePlugin((PluginProxy)getSelection());
        }
        else {
          removeService((TvDataServiceProxy)getSelection());
        }
      }
    });
    
    builder.addButton(mRemove);
    
    contentPanel.add(builder.getPanel(), cc.xyw(1,7,2));
    
    mTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
      public void valueChanged(ListSelectionEvent evt) {
        updateBtns();
      }
    });
    
    updateBtns();

    return contentPanel;
  }

  private Object getSelection() {
    int rowIndex = mTable.getSelectedRow();
    if (rowIndex >= 0) {
      Object proxy = mTableModel.getValueAt(rowIndex, 1);
      mTable.scrollRectToVisible(mTable.getCellRect(rowIndex, 0, true));
      return proxy;
    }
    return null;
  }
  
  private JPopupMenu createContextMenu(final InternalPluginProxyIf plugin) {
    JPopupMenu menu = new JPopupMenu();
    
    //configure
    JMenuItem configureMI;
    configureMI = new JMenuItem(mLocalizer.msg("configure", ""),TVBrowserIcons.preferences(TVBrowserIcons.SIZE_SMALL));
    configureMI.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
          mSettingsDialog.showSettingsTab(plugin.getSettingsId());
        }
      });
    menu.add(configureMI);
    
    //help
    JMenuItem helpMI = new JMenuItem(mLocalizer.msg("pluginHelp","Online help"), IconLoader.getInstance().getIconFromTheme("apps", "help-browser", 16));
    helpMI.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e) {
        String url = PluginInfo.getHelpUrl(plugin.getId());
        Launch.openURL(url);
      }
    });
    menu.add(helpMI);

    return menu;
  }

  private JPopupMenu createContextMenu(final InfoIf plugin) {
    JPopupMenu menu = new JPopupMenu();
    
    //info
    JMenuItem infoMI = new JMenuItem(mLocalizer.msg("info","Info"), IconLoader.getInstance().getIconFromTheme("status", "dialog-information", 16));
    infoMI.setFont(infoMI.getFont().deriveFont(Font.BOLD));
    infoMI.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e) {
        if(plugin instanceof PluginProxy) {
          showInfoDialog((PluginProxy)plugin);
        }
        else if(plugin instanceof TvDataServiceProxy) {
          showInformation((TvDataServiceProxy)plugin);
        }
      }
    });
    menu.add(infoMI);

    //configure
    JMenuItem configureMI;
   	configureMI = new JMenuItem(mLocalizer.msg("configure", ""),TVBrowserIcons.preferences(TVBrowserIcons.SIZE_SMALL));
   	configureMI.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
          if(plugin instanceof PluginProxy) {
            configurePlugin((PluginProxy)plugin);
          }
          else if(plugin instanceof TvDataServiceProxy) {
            configureService((TvDataServiceProxy)plugin);
          }
        }
      });
    menu.add(configureMI);

    if(plugin instanceof PluginProxy) {
      //activate
      JMenuItem enableMI;
      if (((PluginProxy)plugin).isActivated()) {
        enableMI = new JMenuItem(mLocalizer.msg("deactivate", ""),IconLoader.getInstance().getIconFromTheme("actions", "process-stop", 16));
      }
      else {
        enableMI = new JMenuItem(mLocalizer.msg("activate", ""), TVBrowserIcons.refresh(TVBrowserIcons.SIZE_SMALL));
        enableMI.setEnabled(!Settings.propBlockedPluginArray.isBlocked((PluginProxy)plugin));
      }
      enableMI.addActionListener(new ActionListener(){
          public void actionPerformed(ActionEvent e) {
            int row = mTable.getSelectedRow();
            if (row >= 0) {
              mTableModel.setValueAt(!(Boolean)mTableModel.getValueAt(row, 0), row, 0);
            }
          }
        });
      menu.add(enableMI);

      //delete
      JMenuItem deleteMI = new JMenuItem(mLocalizer.msg("remove","Remove"),  TVBrowserIcons.delete(TVBrowserIcons.SIZE_SMALL));
      deleteMI.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
          if(plugin instanceof PluginProxy) {
            removePlugin((PluginProxy)plugin);
          }
          else {
            removeService((TvDataServiceProxy)plugin);
          }
        }
      });
      deleteMI.setEnabled(PluginLoader.getInstance().isPluginDeletable((PluginProxy)plugin));
      menu.add(deleteMI);
    }
    
    //help
      JMenuItem helpMI = new JMenuItem(mLocalizer.msg("pluginHelp","Online help"), IconLoader.getInstance().getIconFromTheme("apps", "help-browser", 16));
      helpMI.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
          String url = PluginInfo.getHelpUrl(plugin.getId());
          Launch.openURL(url);
        }
      });
      menu.add(helpMI);
    
    menu.addSeparator();

    JMenuItem refreshMI = new JMenuItem(mLocalizer.msg("updateInstallPlugin", "Update/Install Plugins"), IconLoader.getInstance().getIconFromTheme("actions", "web-search", 16));
    refreshMI.addActionListener(new ActionListener(){
      public void actionPerformed(ActionEvent e) {
        MainFrame.getInstance().showUpdatePluginsDlg(false);
      }
    });
    menu.add(refreshMI);

    return menu;
  }

  /**
   * Remove a selected Plugin
   */
  private void removePlugin(PluginProxy plugin) {
    if (plugin == null) {
      return;
    }
    String text = mLocalizer.msg("deletePlugin","Really delete the Plugin \"{0}\" ?",plugin.toString());
      
    int result = JOptionPane.showConfirmDialog(mSettingsDialog.getDialog(), text, Localizer.getLocalization(Localizer.I18N_DELETE)+"?", JOptionPane.YES_NO_OPTION);
    if (result == JOptionPane.YES_OPTION) {
        
      if (PluginLoader.getInstance().deletePlugin(plugin)) {
        JOptionPane.showMessageDialog(mSettingsDialog.getDialog(), mLocalizer.msg("successfully","Deletion was succesfully"));
      } else {
        JOptionPane.showMessageDialog(mSettingsDialog.getDialog(), mLocalizer.msg("failed","Deletion failed"));
      }
        
      populatePluginList();
      mSettingsDialog.createPluginTreeItems();
      mTable.setRowSelectionInterval(0, 0);
    }
  }
  
  private void removeService(TvDataServiceProxy service) {
    if (service == null) {
      return;
    }
    
    // count the removed channels
    int channelCount = 0;
    Channel[] subscribed = ChannelList.getSubscribedChannels();
    ArrayList<Channel> keepChannels = new ArrayList<Channel>();
    
    for (Channel element : subscribed) {
      if (!(element instanceof DummyChannel) && element.getDataServiceProxy().equals(service)) {
        channelCount++;
      }
      else {
        keepChannels.add(element);
      }
    }
    
    // show message depending on whether channels will be removed
    String text = mLocalizer.msg("deleteService","Really delete the data service \"{0}\"?",service.getInfo().getName());
    if (channelCount > 0) {
      text = mLocalizer.msg("deleteServiceCount","Really delete the data service \"{0}\"?\nThis will remove {1} of your subscribed channels.",service.getInfo().getName(), channelCount);
    }
    int result = JOptionPane.showConfirmDialog(mSettingsDialog.getDialog(), text, Localizer.getLocalization(Localizer.I18N_DELETE)+"?", JOptionPane.YES_NO_OPTION);
      
    if (result == JOptionPane.YES_OPTION) {
      if (PluginLoader.getInstance().deleteDataService(service)) {
        JOptionPane.showMessageDialog(mSettingsDialog.getDialog(), mLocalizer.msg("dataservice.successfully","Deletion was succesfully"));
        
        ChannelsSettingsTab.saveChannels(keepChannels.toArray(new Channel[keepChannels.size()]), false);
      } else {
        JOptionPane.showMessageDialog(mSettingsDialog.getDialog(), mLocalizer.msg("failed","Deletion failed"));
      }
        
      populatePluginList();
      mTable.setRowSelectionInterval(0, 0);
    }
  }

  /**
   * Show the info dialog
   *
   */
  private void showInfoDialog(PluginProxy plugin) {
    if (plugin == null) {
      return;
    }
    ActionMenu actionMenu = plugin.getButtonAction();
    Action action = null;
    if (actionMenu !=null) {
      action = actionMenu.getAction();
    }
    Icon ico = null;
    if (action != null) {
      ico = (Icon) action.getValue(Action.SMALL_ICON);
    }
    
    if (ico == null) {
      // The plugin has no button icon -> Try the mark icon
      ico = plugin.getMarkIcon();
    }
    
    if (ico == null) {
      ico = new ImageIcon("imgs/Jar16.gif");
    }
    
    PluginInfoDialog dialog = new PluginInfoDialog(mSettingsDialog.getDialog(), ico, plugin.getInfo());
    UiUtilities.centerAndShow(dialog);
  }
  
  /**
   * Show the Info-Dialog for internal plugins
   *
   */
  private void showInfoDialog(InternalPluginProxyIf plugin) {
    JOptionPane.showMessageDialog(UiUtilities.getLastModalChildOf(MainFrame
        .getInstance()), mLocalizer.msg("internalPlugin",
        "This is an internal plugin which cannot be disabled."), mLocalizer
        .msg("internalPluginTitle", "Internal plugin"),
        JOptionPane.INFORMATION_MESSAGE);
  }
  
  private void showInformation(TvDataServiceProxy service) {
    if (service == null) {
      return;
    }
    // show the dialog
    PluginInfoDialog dialog = new PluginInfoDialog(mSettingsDialog.getDialog(), null, service.getInfo());
    UiUtilities.centerAndShow(dialog);
  }

  /**
   * configure the selected plugin (by switching to respective node in dialog)
   */
  private void configurePlugin(PluginProxy plugin) {
    if (plugin == null) {
      return;
    }
    
    mSettingsDialog.showSettingsTab(plugin.getId());
  }
  
  private void configureService(TvDataServiceProxy service) {
    if (service == null) {
      return;
    }
    // show the configuration panel
    mSettingsDialog.showSettingsTab(service.getId());
  }
  
  /**
   * Populate the Plugin-List
   */
  private void populatePluginList() {   
    while (mTableModel.getRowCount() > 0) {
      mTableModel.removeRow(0);
    }
    
    Object test = mFilterBox.getSelectedItem();
    FilterItem filterItem = null;
    
    if(test == null) {
      filterItem = new FilterItem("all");
    }
    else {
      filterItem = (FilterItem)test;
    }
    
    ArrayList<FilterItem> filterItemList = new ArrayList<FilterItem>();
    
    /* Add base plugins */
    
    InternalPluginProxyIf[] internalPluginProxies = InternalPluginProxyList.getInstance().getAvailableProxys();
    Arrays.sort(internalPluginProxies, new InternalPluginProxyIf.Comparator());
    
    for (InternalPluginProxyIf internalPluginProxy : internalPluginProxies) {
      if(filterItem.accept(internalPluginProxy)) {
        mTableModel.addRow(new Object[]{true, internalPluginProxy});
        
        if(mFilterBox.getItemCount() < 1) {
          int index = 0;
    
          for(int i = 0; i < filterItemList.size(); i++) {
            int compareValue = filterItemList.get(i).compareTo(internalPluginProxy.getPluginCategory());
    
            if(compareValue == 0) {
              index = -1;
              break;
            }
            else if(compareValue < 0) {
              index = i+1;
            }
          }
    
          if(index != -1) {
            filterItemList.add(index,new FilterItem(internalPluginProxy.getPluginCategory()));
          }
        }
      }
    }
    
    /* Add plugins and data services */
    PluginProxy[] pluginList = PluginProxyManager.getInstance().getAllPlugins();
    TvDataServiceProxy[] services = TvDataServiceProxyManager.getInstance().getDataServices();
    
    InfoIf[] infoArr = new InfoIf[pluginList.length + services.length];
    
    System.arraycopy(pluginList,0,infoArr,0,pluginList.length);
    System.arraycopy(services,0,infoArr,pluginList.length, services.length);

    Arrays.sort(infoArr, new PluginAndDataServiceComparator());
    
    for (InfoIf info : infoArr) {
      if(filterItem.accept(info)) {
        mTableModel.addRow(new Object[]{(info instanceof PluginProxy) ? ((PluginProxy)info).isActivated() : true, info});
        
        if(mFilterBox.getItemCount() < 1) {
          int index = 0;
    
          for(int i = 0; i < filterItemList.size(); i++) {
            int compareValue = filterItemList.get(i).compareTo(info.getPluginCategory());
    
            if(compareValue == 0) {
              index = -1;
              break;
            }
            else if(compareValue < 0) {
              index = i+1;
            }
          }
    
          if(index != -1) {
            filterItemList.add(index,new FilterItem(info.getPluginCategory()));
          }
        }
      }
    }
    
    /*for(SoftwareUpdateItem item : itemArr) {
      int index = 0;

      for(int i = 0; i < filterList.size(); i++) {
        int compareValue = filterList.get(i).compareTo(item.getCategory());

        if(compareValue == 0) {
          index = -1;
          break;
        }
        else if(compareValue < 0) {
          index = i+1;
        }
      }

      if(index != -1) {
        filterList.add(index,new FilterItem(item.getCategory()));
      }
    }*/

    if(mFilterBox.getItemCount() < 1) {
      if(!filterItemList.contains(new FilterItem("all"))) { 
        filterItemList.add(0, new FilterItem("all"));
      }
      
      for(FilterItem item : filterItemList) {
        mFilterBox.addItem(item);
      }
    }
    
  /*  for (TvDataServiceProxy service : services) {
      mTableModel.addRow(new Object[]{true, service});
    }
    
    Arrays.sort(pluginList, new PluginProxy.Comparator());

    for (PluginProxy element : pluginList) {
      mTableModel.addRow(new Object[]{Boolean.valueOf(element.isActivated()),element});
    }*/

  }

  /**
   * Updates the State of the Buttons
   *
   */
  private void updateBtns() {
    int rowIndex = mTable.getSelectedRow();
    Object plugin = null;
    if (rowIndex >= 0) {
      plugin = mTable.getValueAt(rowIndex, 1);
    }

    mInfo.setEnabled(plugin != null && (plugin instanceof PluginProxy || plugin instanceof TvDataServiceProxy));
    mRemove.setEnabled(plugin != null && ((plugin instanceof PluginProxy && PluginLoader.getInstance().isPluginDeletable((PluginProxy)plugin)) ||
        (plugin instanceof TvDataServiceProxy && PluginLoader.getInstance().isDataServiceDeletable((TvDataServiceProxy)plugin))));
    mConfigure.setEnabled(plugin != null);
  }

  /**
   * Start/Stop was clicked
   * 
   * @param plugin Plugin that is started/stopped
   */
  private void onStartStopBtnClicked(PluginProxy plugin) {
    if (plugin != null) {
      try {
        if (plugin.isActivated()) {
          PluginProxyManager.getInstance().deactivatePlugin(plugin);
        } else {
          PluginProxyManager.getInstance().activatePlugin(plugin, true);
          try {
            PluginProxyManager.getInstance().fireTvBrowserStartFinished(plugin);
          }catch(Throwable t) {
            /* Catch all possible not catched errors that occur in the plugin mehtod*/
            mLog.log(Level.WARNING, "A not catched error occured in 'fireTvBrowserStartFinishedThread' of Plugin '" + plugin +"'.", t);
          }
        }
      } catch (TvBrowserException exc) {
        ErrorHandler.handle(exc);
      }

      mTable.repaint();
      updateBtns();
      mSettingsDialog.invalidateTree();
      mSettingsDialog.createPluginTreeItems();
      MainFrame.getInstance().getToolbar().updatePluginButtons();
    }

    // Update the settings
    String[] deactivatedPlugins = PluginProxyManager.getInstance().getDeactivatedPluginIds();
    Settings.propDeactivatedPlugins.setStringArray(deactivatedPlugins);
  }

  public void saveSettings() {
    
  }

  public Icon getIcon() {
    return TVBrowserIcons.plugin(TVBrowserIcons.SIZE_SMALL);
  }

  public String getTitle() {
    return mLocalizer.msg("plugins", "Plugins");
  }

  public void tableChanged(TableModelEvent e) {
    int row = e.getFirstRow();
    int column = e.getColumn();
    if (column == 0) {
      Cursor oldCursor = mTable.getCursor();
      mTable.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
      Object plugin = mTableModel.getValueAt(row, 1);
      if (plugin instanceof PluginProxy) {
        onStartStopBtnClicked((PluginProxy) plugin);
      }
      mTable.setCursor(oldCursor);
    }
  }
  
 /* private class FilterItem {
    private String mCategory;
    
    public FilterItem(String category) {
      mCategory = category;
    }
    
    public String toString() {
      return SoftwareUpdateDlg.mLocalizer.msg(mCategory,mCategory);
    }
  }*/

}
