package org.limewire.ui.swing.options;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
import javax.swing.ScrollPaneConstants;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

import net.miginfocom.swing.MigLayout;

import org.jdesktop.swingx.JXButton;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.table.TableColumnExt;
import org.limewire.core.api.Category;
import org.limewire.core.api.file.CategoryManager;
import org.limewire.ui.swing.components.FocusJOptionPane;
import org.limewire.ui.swing.components.MultiLineLabel;
import org.limewire.ui.swing.components.decorators.ButtonDecorator;
import org.limewire.ui.swing.components.decorators.TableDecorator;
import org.limewire.ui.swing.options.actions.OKDialogAction;
import org.limewire.ui.swing.table.DefaultLimeTableCellRenderer;
import org.limewire.ui.swing.util.I18n;
import org.limewire.ui.swing.util.IconManager;
import org.limewire.util.OSUtils;

// 00000 This seems useful, but it seems like it's been unlinked.  What gives?

import com.google.inject.Inject;

/**
 * A panel that simply displays the current file to category associations being used.
 */
public class ExtensionClassificationPanel extends JPanel {

    private static final Category[] ALL_CATEGORIES = Category.values();
    
    private static final String TABLE_VIEW = "TABLE_VIEW";
    private static final String OTHER_VIEW = "OTHER_VIEW";
    
    private final CategoryManager categoryManager;
    private final IconManager iconManager;
    private final ButtonDecorator buttonDecorator;
    
    private final JXTable table;
    private final JPanel contentPanel;
    private final CardLayout contentSwitcher;
    
    private Category[] currentCategories = null;
    
    private final JPanel switchPanel;
    
    @Inject
    public ExtensionClassificationPanel(CategoryManager categoryManager, IconManager iconManager,
            TableDecorator tableDecorator, ButtonDecorator buttonDecorator) {

        super(new BorderLayout());
        
        this.categoryManager = categoryManager;
        this.iconManager = iconManager;
        this.buttonDecorator = buttonDecorator;
                
        setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
        setOpaque(false);
        
        add(new JLabel("<html>"+I18n.tr("WireShare knows about these extensions and classifies them as follows:")+"</html>"),
            BorderLayout.NORTH);
        
        
        JPanel centerPanel = new JPanel(new BorderLayout());
        centerPanel.setOpaque(false);
        
        switchPanel = new JPanel(new MigLayout("insets 10, gap 5"));
        switchPanel.setOpaque(false);
        
        centerPanel.add(switchPanel, BorderLayout.NORTH);
        
        table = new JXTable(); 
        tableDecorator.decorate(table);        
        
        table.setShowGrid(false, false);
        table.setColumnSelectionAllowed(false);
        table.setSelectionMode(0);
        table.setDefaultRenderer(Object.class, new DefaultLimeTableCellRenderer());
        
        JScrollPane scrollPane = new JScrollPane(table, 
                ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, 
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        scrollPane.setOpaque(false);
        
        contentSwitcher = new CardLayout();
        contentPanel = new JPanel(contentSwitcher);
        contentPanel.setOpaque(false);
        
        contentPanel.add(scrollPane, TABLE_VIEW);
        
        JPanel otherPanel = new JPanel(new GridBagLayout());
        otherPanel.setOpaque(false);
        
	//3456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
        JLabel otherLabel = new MultiLineLabel(I18n.tr("Unknown file types are classified " +
	"as \"Other\"; to categorize them, simply drag and drop them onto the relevant " +
	"category.  If adding several file types, drag and drop the folder they are in, click " +
	"\"Advanced\", and then choose the specific file extensions to associate."), 450);
        otherLabel.setOpaque(false);
        
        otherPanel.add(otherLabel);
        
        contentPanel.add(otherPanel, OTHER_VIEW);
        
        centerPanel.add(contentPanel, BorderLayout.CENTER);
        add(centerPanel, BorderLayout.CENTER);

    }

    /**
     * Builds a table model containing the extension association information for a given
     *  set of categories. 
     */
    private TableModel createTableModel(Category... categories) {
        
        Collection<String> extensions = new HashSet<String>();
        for ( Category category : categories ) {
            extensions.addAll(categoryManager.getExtensionsForCategory(category));
        }
        
        List<String> sortedList = new ArrayList<String>(extensions);
        Collections.sort(sortedList);
        extensions = sortedList;
        
        List<String> headingList = new ArrayList<String>();
        headingList.add(""); // Icon
        headingList.add(I18n.tr("Extension"));
        if (categories.length > 1) {
            headingList.add(I18n.tr("Category"));
        }
        if (OSUtils.isWindows()) {
            headingList.add(I18n.tr("Type"));
        }
        
        Object[][] data = new Object[extensions.size()][headingList.size()];
        
        int y = 0;
        for ( String ext : extensions ) {
            int x = 0;
            
            Icon icon = iconManager.getIconForExtension(ext);
            
            data[y][x++] = icon;
            data[y][x++] = ext;
            
            if (categories.length > 1) {
                data[y][x++] = I18n.tr(categoryManager.getCategoryForExtension(ext).getSingularName());
            }
            if (OSUtils.isWindows() && icon != null) {
                if (!icon.toString().startsWith("file:/")) {
                    data[y][x++] = icon.toString();
                }
            }
               
            y++;
        }
        
        return new DefaultTableModel(data, headingList.toArray()) {
            @Override
            public Class<?> getColumnClass(int column) {
                if (column == 0) {
                    return Icon.class;
                }
                else {
                    return String.class;
                }
            }
        };
    }
    
    private class CategorySwitchAction extends AbstractAction {
        
        private final Category[] categoriesForSwitch;
        
        public CategorySwitchAction(String name, Category... categoriesForSwitch) {
            super(name);
            this.categoriesForSwitch = categoriesForSwitch;
        }
        
        public CategorySwitchAction(Category... categoriesForSwitch) {
            super(I18n.tr(categoriesForSwitch[0].getPluralName()));
            this.categoriesForSwitch = categoriesForSwitch;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            switchCategory(categoriesForSwitch);
            updateSelection((JButton)e.getSource());
        }
        
        public Category[] getCategoriesForSwitch() {
            return categoriesForSwitch;
        }
    }
    
    /**
     * Switch the visible tab to the one containing the category.
     * 
     * <p> Null category implies the all category as a shortcut if
     *      ever needed
     */
    public void switchCategory(Category category) {
        if (category == null) {
            switchCategory(ALL_CATEGORIES);
        } 
        else {
            switchCategory(new Category[] {category});
        }
        updateSelection(category);
    }
    
    private void switchCategory(Category... categories) {
        
        if (categories == currentCategories) {
            return;
        }
        
        if (categories.length == 1 && categories[0] == Category.OTHER) {
            contentSwitcher.show(contentPanel, OTHER_VIEW);
        }
        else {
            contentSwitcher.show(contentPanel, TABLE_VIEW);
        }
        
        currentCategories = categories;
        TableModel model = createTableModel(currentCategories);

        table.setModel(model);
        TableColumnExt iconColumn = table.getColumnExt(model.getColumnName(0));
        iconColumn.setResizable(false);
        iconColumn.setMinWidth(16);
        iconColumn.setMaxWidth(16);
        iconColumn.setWidth(16);
        iconColumn.setComparator(new Comparator<ImageIcon>() {
            @Override
            public int compare(ImageIcon o1, ImageIcon o2) {
                return o1.getImage().toString().compareTo(o2.getImage().toString());
            }
        });
    }
    
    private void updateSelection(JButton button) {
        button.setSelected(true);
        for ( Component comp : switchPanel.getComponents() ) {
            if (comp instanceof JButton && button != comp) {
                ((JButton)comp).setSelected(false);
            }
        }
    }
    
    private void updateSelection(Category category) {
        for ( Component comp : switchPanel.getComponents() ) {
            if (comp instanceof JButton) {
                JButton button = ((JButton)comp);
                Category[] categoriesForSwitch = ((CategorySwitchAction)button.getAction()).getCategoriesForSwitch();
                if (category == null) {
                    button.setSelected(categoriesForSwitch.length > 1);
                } else {
                    button.setSelected(categoriesForSwitch.length != 0 && categoriesForSwitch[0] == category);
                }
            }
        }
    }
    
    private JButton createSelectionButton(Action action) {
        JXButton button = new JXButton(action);
        button.setModel(new JToggleButton.ToggleButtonModel());
        buttonDecorator.decorateLinkButton(button);
        return button;
    }
    
    /**
     * Loads the panel for use.  Builds the table and lays out the component.
     */
    public void init() {
        if (currentCategories == null) { 
            switchCategory(ALL_CATEGORIES);
        }
        
        switchPanel.removeAll();
        switchPanel.invalidate();
        
        switchPanel.add(new JLabel(I18n.tr("Show:")));
        
        JButton allButton = createSelectionButton(new CategorySwitchAction(I18n.tr("All"), ALL_CATEGORIES));
        allButton.setSelected(currentCategories == ALL_CATEGORIES);
        
        switchPanel.add(allButton);
        
        for ( Category category : ALL_CATEGORIES ) {
            JButton categoryButton = createSelectionButton(new CategorySwitchAction(category));
            categoryButton.setSelected(currentCategories.length == 1 && category == currentCategories[0]);
            switchPanel.add(categoryButton);
        }
    }

    public void showDialogue() {
        init();
        JDialog dialog = FocusJOptionPane.createDialog(I18n.tr("File Extension Classification"), null, this);
        
        JPanel buttonPanel = new JPanel(new MigLayout("insets 0 0 10 10, gap 4, fill"));
        buttonPanel.setOpaque(false);
        buttonPanel.add(new JButton(new OKDialogAction()), "tag ok");
        dialog.getContentPane().add(buttonPanel, BorderLayout.SOUTH);
        
        dialog.pack();
        
        table.requestFocusInWindow();
        dialog.setVisible(true);
        
    }
}
