/*
 * The contents of this file are subject to the terms of the Common Development
 * and Distribution License (the License). You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
 * or http://www.netbeans.org/cddl.txt.
 * 
 * When distributing Covered Code, include this CDDL Header Notice in each file
 * and include the License file at http://www.netbeans.org/cddl.txt.
 * If applicable, add the following below the CDDL Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * The Original Software is NetBeans. The Initial Developer of the Original
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.options.ui;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Vector;
import javax.swing.AbstractButton;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import org.openide.util.Utilities;



/**
 */
public class TabbedPanel extends JPanel {
    
    public static int               EXPAND_ONE = 1;
    public static int               EXPAND_SOME = 2;
    public static int               EXPAND_ALL = 3;
    
    
    private static Color            bColor = new Color (
        Math.max ((int)(SystemColor.control.getRed ()   * 0.9), 0), 
		Math.max ((int)(SystemColor.control.getGreen () * 0.9), 0),
		Math.max ((int)(SystemColor.control.getBlue ()  * 0.9), 0)
    );
    
    private TabbedPanelModel        model;
    private int                     selectedIndex = -1;
    private Set                     selectedIndexes = new HashSet ();
    private int                     expansionPolicy;
    private boolean                 fill;
    private JComponent              selectedComponent;
    private JComponent[]            titles;
    private Vector                  listeners = new Vector ();
    

    public TabbedPanel (
        TabbedPanelModel model,
        int expansionPolicy,
        boolean fill
    ) {
        this.model = model;
        this.expansionPolicy = expansionPolicy;
        this.fill = fill;
        addKeyListener (listener);
        refreshPanels ();
        setBorder (new LineBorder (new Color (127, 157, 185)));
    }
    
    public int getExpansionPolicy () {
        return expansionPolicy;
    }
    
    public int getSelectedIndex () {
        return selectedIndex;
    }
    
    public boolean isExpanded (int index) {
        if (index == selectedIndex) return true;
        return selectedIndexes.contains (new Integer (index));
    }
    
    public void setSelectedIndex (final int index) {
        final int ii = index >= 0 ? index : selectedIndex;
        if (expansionPolicy == EXPAND_ALL) {
            Integer i = new Integer (index);
            if (!selectedIndexes.remove (i))
                selectedIndexes.add (i);
        } else
            selectedIndex = index;
        refreshPanels ();
        SwingUtilities.invokeLater (new Runnable () {
            public void run () {
                if (ii >= 0)
                    titles [ii].requestFocus ();
            }
        });
    }
    
    public JComponent getSelectedComponent () {
        return selectedComponent;
    }
    
    public String getSelectedCategory () {
        int i = getSelectedIndex ();
        if (i < 0) return null;
        return (String) model.getCategories ().get (i);
    }
    
    public void addActionListener (ActionListener listener) {
        listeners.add (listener);
    }
    
    public void removeActionListener (ActionListener listener) {
        listeners.remove (listener);
    }
    
    protected void fireActionPerformed (ActionEvent event) {
        Vector l = (Vector) listeners.clone ();
        Iterator it = l.iterator ();
        while (it.hasNext ())
            ((ActionListener) it.next ()).actionPerformed (event);
    }
    
    public void refreshPanels () {
        removeAll ();
        selectedComponent = null;
        
        if (expansionPolicy == EXPAND_ONE &&
            selectedIndex < 0
        ) selectedIndex = 0;
        
        FormLayout layout = new FormLayout ("p:g", "");
        CellConstraints cc = new CellConstraints ();
        setLayout (layout);
        List categories = model.getCategories ();
        int i, k = categories.size (), j = 1;
        titles = new JComponent [k];
        for (i = 0; i < k; i++) {      
            JComponent l = createTitleComponent ((String) categories.get (i), i);
            layout.appendRow (new RowSpec ("p"));
            add (l, cc.xy (1, j++, "l,c"));
            titles [i] = l;
    
            if ( (expansionPolicy == EXPAND_ALL && 
                  selectedIndexes.contains (new Integer (i))
                 ) ||
                 i == selectedIndex
            ) {
                selectedComponent = model.getPanel ((String) categories.get (i));
                layout.appendRow (new RowSpec (fill ? "f:p:g" : "f:p"));
                add (selectedComponent, cc.xy (1, j++));
            }
        }
        revalidate ();
        repaint ();
        fireActionPerformed (new ActionEvent (this, 0, "selectedIndex"));
    }

    protected JComponent createTitleComponent (
        String name,
        int index
    ) {
        JLabel l = new JLabel (
            name,
            new ImageIcon (Utilities.loadImage (
                index == selectedIndex ?
                    "org/netbeans/modules/options/resources/expanded.gif":
                    "org/netbeans/modules/options/resources/collapsed.gif"
            )),
            JButton.LEFT
        );
        l.setFont (l.getFont ().deriveFont (Font.BOLD));
        l.setBackground (bColor);
        l.setOpaque (true);
        l.putClientProperty ("index", new Integer (index));
        l.addMouseListener (listener);
        l.setBorder (new EmptyBorder (1, 1, 1, 1));
//        l.setBorder (new BevelBorder (
//            BevelBorder.RAISED,
//            SystemColor.control.brighter (),
//            SystemColor.control,
//            SystemColor.control.darker (),
//            SystemColor.control
//         ));
        l.setCursor (Cursor.getPredefinedCursor (Cursor.HAND_CURSOR));
        return l;
    }


    private Listener listener = new Listener ();
    
    private class Listener implements ActionListener, KeyListener, 
    MouseListener {
        public void actionPerformed (ActionEvent e) {
            AbstractButton b = (AbstractButton) e.getSource ();
            int i = ((Integer) b.getClientProperty ("index")).intValue ();
            if (i == selectedIndex)
                setSelectedIndex (-1);
            else
                setSelectedIndex (i);
        }    

        public void keyTyped (KeyEvent e) {
            
        }

        public void keyPressed (KeyEvent e) {}
        public void keyReleased (KeyEvent e) {}
        
        public void mouseClicked (MouseEvent e) {
            if (!(e.getSource () instanceof JLabel)) return;
            JLabel l = (JLabel) e.getSource ();
            int i = ((Integer) l.getClientProperty ("index")).intValue ();
            if (i == selectedIndex) {
                if (expansionPolicy != EXPAND_ONE)
                    setSelectedIndex (-1);
            } else
                setSelectedIndex (i);
        }
        
        public void mousePressed (MouseEvent e) {}
        public void mouseReleased (MouseEvent e) {}
        
        public void mouseEntered (MouseEvent e) {
            if (!(e.getSource () instanceof JLabel)) return;
            JLabel l = (JLabel) e.getSource ();
            l.setBackground (SystemColor.control);
            revalidate ();
            repaint ();
        }
        
        public void mouseExited (MouseEvent e) {
            if (!(e.getSource () instanceof JLabel)) return;
            JLabel l = (JLabel) e.getSource ();
            l.setBackground (bColor);
            revalidate ();
            repaint ();
        }
    };
}





