/*
 *  PHEX - The pure-java Gnutella-servent.
 *  Copyright (C) 2001 - 2004 Gregor Koukkoullis ( phex <at> kouk <dot> de )
 *
 *  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
 */
package phex.query;

import java.io.*;
import java.util.*;

import javax.xml.bind.*;

import phex.common.*;
import phex.event.*;
import phex.utils.*;
import phex.xml.*;

public class SearchFilterContainer
{
    private ArrayList searchFilterList;

    public SearchFilterContainer()
    {
        searchFilterList = new ArrayList();
        loadSearchFilters();
    }

    /**
     * Returns the number of available search filters.
     * @return the number of available search filters.
     */
    public int getSearchFilterCount()
    {
        return searchFilterList.size();
    }

    /**
     * Returns the search filter at index.
     * @param index the index
     * @return the search filter at index.
     */
    public SearchFilter getSearchFilterAt( int index )
    {
        if ( index < 0 || index >= searchFilterList.size() )
        {
            return null;
        }
        return (SearchFilter) searchFilterList.get( index );
    }

    /**
     * Returns a search filter for name. If no search filter could be found
     * null is returned.
     * @param name The name of the search filter to look for
     * @return the SearchFilter if found or null.
     */
    public SearchFilter getSearchFilterWithName( String name )
    {
        name = name.trim();
        SearchFilter filter;
        for ( int i = searchFilterList.size() - 1; i >= 0; i-- )
        {
            filter = (SearchFilter)searchFilterList.get( i );
            if ( filter.getName().equals( name ) )
            {
                return filter;
            }
        }
        return null;
    }

    /**
     * Adds a new search filter to the list.
     * @param searchFilter The search filter to add.
     */
    public void addSearchFilter( SearchFilter searchFilter )
    {
        searchFilterList.add( 0, searchFilter );
        fireSearchFilterAdded( 0 );
    }

    /**
     * Removes a search filter from the list.
     * @param searchFilter The search filter to remove.
     */
    public void removeSearchFilter( SearchFilter searchFilter )
    {
        int idx = searchFilterList.indexOf( searchFilter );
        if ( idx > -1 )
        {
            searchFilterList.remove( idx );
            saveSearchFilters();
            fireSearchFilterRemoved( idx );
        }
    }

    public void saveSearchFilters()
    {
        Logger.logMessage( Logger.CONFIG, Logger.SEARCH,
            "Saving search filters..." );
            
        if ( searchFilterList.size() == 0 )
        {
            // no filters to save available...
            // skip save and delete possible old file
            File file = Environment.getInstance().getPhexConfigFile(
                EnvironmentConstants.XML_FILTER_LIST_FILE_NAME );
            file.delete();
        }

        // JAXB-beta way
        try
        {
            XJBPhex phex = ObjectFactory.createPhexElement();
            phex.setPhexVersion( VersionUtils.getProgramVersion() );

            XJBSearchFilters xjbFilters = ObjectFactory.createXJBSearchFilters();
            phex.setSearchFilters( xjbFilters );

            List xjbFilterList = xjbFilters.getSearchFilterList();
            SearchFilter filter;
            XJBSearchFilter xjbFilter;
            for ( int i = searchFilterList.size() - 1; i >= 0; i-- )
            {
                filter = (SearchFilter)searchFilterList.get( i );
                xjbFilter = filter.createXJBSearchFilter();
                xjbFilterList.add( xjbFilter );
            }

            File file = Environment.getInstance().getPhexConfigFile(
                EnvironmentConstants.XML_FILTER_LIST_FILE_NAME );
            XMLBuilder.saveToFile( file, phex );
        }
        catch ( JAXBException exp )
        {
            // TODO bring a GUI message that file cant be created
            Logger.logError( exp );
        }

    }

    public void loadSearchFilters()
    {
        Logger.logMessage( Logger.CONFIG, Logger.SEARCH,
            "Loading search filters..." );

        // JAXB-BETA way
        File file = Environment.getInstance().getPhexConfigFile(
            EnvironmentConstants.XML_FILTER_LIST_FILE_NAME );
        XJBPhex phex;
        try
        {
            phex = XMLBuilder.loadXJBPhexFromFile( file );
            if ( phex == null )
            {
                return;
            }
        }
        catch ( JAXBException exp )
        {
            // TODO bring a GUI message that file cant be created
            Logger.logError( exp );
            return;
        }

        List xjbFilterList = phex.getSearchFilters().getSearchFilterList();
        SearchFilter filter;
        XJBSearchFilter xjbFilter;
        Iterator iterator = xjbFilterList.iterator();
        while( iterator.hasNext() )
        {
            try
            {
                xjbFilter = (XJBSearchFilter)iterator.next();
                filter = SearchFilter.createFromxJBSearchFilter( xjbFilter );
                searchFilterList.add( filter );
            }
            catch ( Exception exp )
            {// catch all exception in case we have an error in the XML
                Logger.logError( exp,
                    "Error loading a search filter from XML." );
            }
        }

    }




    ///////////////////// START event handling methods ////////////////////////

    /**
     * All listeners interested in events.
     */
    private ArrayList listenerList = new ArrayList( 2 );

    public void addSearchFilterListListener( SearchFilterListListener listener )
    {
        listenerList.add( listener );
    }

    public void removeSearchListChangeListener( SearchFilterListListener listener )
    {
        listenerList.remove( listener );
    }

    protected void fireSearchFilterChanged( final int position )
    {
        // invoke update in event dispatcher
        AsynchronousDispatcher.invokeLater(
        new Runnable()
        {
            public void run()
            {
                Object[] listeners = listenerList.toArray();
                SearchFilterListListener listener;
                // Process the listeners last to first, notifying
                // those that are interested in this event
                for ( int i = listeners.length - 1; i >= 0; i-- )
                {
                    listener = (SearchFilterListListener)listeners[ i ];
                    listener.searchFilterChanged( position );
                }
            }
        });
    }

    protected void fireSearchFilterAdded( final int position )
    {
        // invoke update in event dispatcher
        AsynchronousDispatcher.invokeLater(
        new Runnable()
        {
            public void run()
            {
                Object[] listeners = listenerList.toArray();
                SearchFilterListListener listener;
                // Process the listeners last to first, notifying
                // those that are interested in this event
                for ( int i = listeners.length - 1; i >= 0; i-- )
                {
                    listener = (SearchFilterListListener)listeners[ i ];
                    listener.searchFilterAdded( position );
                }
            }
        });
    }

    protected void fireSearchFilterRemoved( final int position )
    {
        // invoke update in event dispatcher
        AsynchronousDispatcher.invokeLater(
        new Runnable()
        {
            public void run()
            {
                Object[] listeners = listenerList.toArray();
                SearchFilterListListener listener;
                // Process the listeners last to first, notifying
                // those that are interested in this event
                for ( int i = listeners.length - 1; i >= 0; i-- )
                {
                    listener = (SearchFilterListListener)listeners[ i ];
                    listener.searchFilterRemoved( position );
                }
            }
        });
    }

    protected void fireSearchFilterChanged( SearchFilter search )
    {
        int position = searchFilterList.indexOf( search );
        if ( position >= 0 )
        {
            fireSearchFilterChanged( position );
        }
    }
    ///////////////////// END event handling methods ////////////////////////
}