/*
 * 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 java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.swing.AbstractListModel;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;


/**
 * This implementation of ListModel caches all readed values, and manages all
 * chages of datas.
 */
public abstract class AdvancedListModel extends ListModel {

    
    // Map (String - Model)
    private Map         categoryToModel = new HashMap ();
    private Map         categoryToOriginalItems = new HashMap ();
    
    
    public AdvancedListModel (
        int layoutOrientation,
        boolean useScrolls,
        int selectionMode
    ) {
        super (layoutOrientation, useScrolls, selectionMode);
    }
    
    public JComponent getPanel (String category) {
        ListCellRenderer renderer = getListCellRenderer ();
        Model model = (Model) categoryToModel.get (category);
        if (model == null) {
            List l = getItems (category);
            categoryToOriginalItems.put (category, l);
            model = new Model (l);
            categoryToModel.put (category, model);
        }
        JList l = new JList (model);
        l.setLayoutOrientation (layoutOrientation);
        l.setCellRenderer (renderer);
        l.setSelectionMode (selectionMode);
        if (useScrolls) {
            JScrollPane scrollPane = new JScrollPane (
                l,
                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
            );
            scrollPane.setBorder (null);
            return scrollPane;
        }
        return l;
    }
    
    /**
     * Returns modified categories and items in format Map (String, List).
     */
    public Map getModifiedItems () {
        Iterator it = categoryToOriginalItems.keySet ().iterator ();
        Map result = new HashMap ();
        while (it.hasNext ()) {
            String category = (String) it.next ();
            if (!categoryToOriginalItems.get (category).equals (
                   categoryToModel.get (category)
            )) result.put (
                category, 
                ((Model) categoryToModel.get (category)).getItems ()
            );
        }
        return result;
    }

    public void insert (
        String category,
        int index,
        Object item
    ) {
        Model model = (Model) categoryToModel.get (category);
        model.insert (index, item);
    }

    public void moveDown (
        String category,
        int index
    ) {
        Model model = (Model) categoryToModel.get (category);
        model.moveDown (index);
    }

    public void moveUp (
        String category,
        int index
    ) {
        Model model = (Model) categoryToModel.get (category);
        model.moveUp (index);
    }

    public void remove (
        String category,
        int index
    ) {
        Model model = (Model) categoryToModel.get (category);
        model.remove (index);
    }
    
    
    private static class Model extends AbstractListModel {
        
        private List list;
        
        Model (List list) {
            this.list = list;
        }
        
        public int getSize () {
            return list.size ();
        }

        public Object getElementAt (int index) {
            return list.get (index);
        }

        public void insert (
            int index,
            Object item
        ) {
            list.add (index, item);
            fireIntervalAdded (this, index, index);
        }

        public void moveDown (
            int index
        ) {
            Object o = list.remove (index);
            list.add (index + 1, o);
            fireContentsChanged (this,  index, index + 1);
        }

        public void moveUp (
            int index
        ) {
            Object o = list.remove (index);
            list.add (index - 1, o);
            fireContentsChanged (this,  index - 1, index);
        }

        public void remove (
            int index
        ) {
            list.remove (index);
            fireIntervalRemoved (this,  index, index);
        }
        
        public List getItems () {
            return list;
        }
    }
}





