/*******************************************************************************
* Copyright (c)                                                                *
*           2005   Tristan Allwood,                                            *
*           2005   Daniel Burke,                                               *
*           2005   Marc Hull,                                                  *
*           2005   Ekaterina Itskova,                                          *
*           2005   Steve Zymler                                                *
*                                                                              *
* Permission is hereby granted, free of charge, to any person obtaining a      *
* copy of this software and associated documentation files (the                *
* "Software"), to deal in the Software without restriction, including          *
* without limitation the rights to use, copy, modify, merge, publish,          *
* distribute, sublicense, and/or sell copies of the Software, and to           *
* permit persons to whom the Software is furnished to do so, subject to        *
* the following conditions:                                                    *
*                                                                              *
* The above copyright notice and this permission notice shall be included      *
* in all copies or substantial portions of the Software.                       *
*                                                                              *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS      *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF                   *
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.       *
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY         *
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,         *
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE            *
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                       *
*******************************************************************************/
/*
 * Created on 26-Nov-2004
 *
 */
package uk.ac.ic.doc.kevlar.gui.internal.keyboard;

import java.util.ArrayList;
import java.util.Collections;

import org.eclipse.swt.graphics.Rectangle;

import uk.ac.ic.doc.kevlar.gui.internal.ADrawableObject;
import uk.ac.ic.doc.kevlar.gui.internal.pipeline.PipeLineManager;
import uk.ac.ic.doc.kevlar.gui.internal.pipeline.Program;
import uk.ac.ic.doc.kevlar.gui.internal.pipeline.comparators.TabOrderComparator;
import uk.ac.ic.doc.kevlar.gui.internal.widgets.IDimensionListener;

/**
 * @author Marc
 **/
public class TabManager implements IDimensionListener {

    private static TabManager singleton;
    
    protected ArrayList<Program> tabList;
    protected ArrayList<Program> filteredList;
    protected String filter;
    protected boolean reorder;
    
    private TabManager() {
        
        tabList = new ArrayList<Program>();
        filteredList = new ArrayList<Program>();
        filter = "";
        reorder = false;
        
    }
    
    public static TabManager getSingleton() {
        
        return singleton;
        
    }
    
    public static void createSingleton() {
        
        if (singleton == null) {
            
            singleton = new TabManager();
            
        }
        
    }
    
    public void addToTabList(Program p) {
        
        if (!tabList.contains(p)) {
            
            tabList.add(p);
            p.addDimensionListener(this);
            
            if (matchesFilter(p)) {
                
                filteredList.add(p);
                reorder = true;
                
            }
            
        }
        
    }
    
    public void removeFromTabList(Program p) {
        
        if (tabList.contains(p)) {
        
            p.removeDimensionListener(this);
            tabList.remove(p);
            filteredList.remove(p);
            
        }
        
    }
    
    public void setFilter(String f) {
        
        String lf = f.toLowerCase();
        
        if (lf.startsWith(filter)) {
            
            filter = lf;
            removeFromFilterList();
            
        } else {
            
            filter = lf;
            recalculateFilterList();
            
        }
        
        Program selected = PipeLineManager.getSingleton().getSelectedProgram();
        
        if (selected == null || !selected.isEnabled()) {
            
            Program next = getNextProgram(null);
            
            if (next != null) {
            
                PipeLineManager.getSingleton().selectProgram(next);
                
            }
            
        }
        
    }
    
    private boolean matchesFilter(Program p) {
        
        return (p.getName().toLowerCase().startsWith(filter));
        
    }
    
    private void removeFromFilterList() {
        
        int i = 0;
        
        while (i < filteredList.size()) {
            
            Program p = filteredList.get(i);
            
            if (!matchesFilter(p)) {
                
                filteredList.get(i).disable();
                filteredList.remove(i);
                
            } else {
                
                i++;
                
            }
            
        }
        
    }
    
    private void recalculateFilterList() {
        
        filteredList.clear();
        
        for (Program p : tabList) {
            
            if (matchesFilter(p)) {
                
                filteredList.add(p);
                p.enable();
                
            } else {
                
                p.disable();
                
            }
            
        }

        reorder = true;
        
    }
    
    public Program getNextProgram(Program current) {
        
        if (reorder) {
                        
            Collections.sort(filteredList, new TabOrderComparator());
            reorder = false;
            
        }
        
        int currentIndex = filteredList.indexOf(current);
        
        if (currentIndex >= 0) {
            
            currentIndex++;
            
            if (currentIndex >= filteredList.size()) {
                
                currentIndex = 0;
                
            }
            
            return filteredList.get(currentIndex);
            
        } else if (!filteredList.isEmpty()){
            
            if (filteredList.contains(PipeLineManager.getSingleton().getLastSelectedProgram())) {
                
                return PipeLineManager.getSingleton().getLastSelectedProgram();
                
            }
            
            return filteredList.get(0);
            
        } else {
            
            return current;
            
        }
        
    }
    
    public Program getPreviousProgram(Program current) {
        
        if (reorder) {
                        
            Collections.sort(filteredList, new TabOrderComparator());
            reorder = false;
            
        }
        
        int currentIndex = filteredList.indexOf(current);
        
        if (currentIndex >= 0) {
            
            currentIndex--;
            
            if (currentIndex <= -1) {
                
                currentIndex = filteredList.size()-1;
                
            }
            
            return filteredList.get(currentIndex);
            
        } else if (!filteredList.isEmpty()){
            
            if (filteredList.contains(PipeLineManager.getSingleton().getLastSelectedProgram())) {
                
                return PipeLineManager.getSingleton().getLastSelectedProgram();
                
            }
            
            return filteredList.get(0);
            
        } else {
            
            return current;
            
        }
        
    }
    
    public void reorder() {

        reorder = true;
        
    }

    public void objectDimensionsChanged(ADrawableObject object, Rectangle dimensions) {

        reorder = true;
        
    }
    
}
