/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.modules.tasklist.impl;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.netbeans.modules.tasklist.filter.TaskFilter;
import org.netbeans.modules.tasklist.trampoline.TaskGroup;
import org.netbeans.spi.tasklist.FileTaskScanner;
import org.netbeans.spi.tasklist.PushTaskScanner;
import org.netbeans.spi.tasklist.Task;
import org.openide.filesystems.FileObject;
import org.openide.util.WeakSet;

/**
 * @author S. Aubrecht
 * @author Tomas Stupka
 */
public class TaskList {
    
    private TreeSet<Task> sortedTasks;
    private ArrayList<Task> tasksList;
    
    private Map<PushTaskScanner, List<Task>> pushScanner2tasks = new HashMap<PushTaskScanner, List<Task>>( 10 );
    private Map<FileTaskScanner, List<Task>> fileScanner2tasks = new HashMap<FileTaskScanner, List<Task>>( 10 );
    
    private Map<TaskGroup, List<Task>> group2tasks = new HashMap<TaskGroup,List<Task>>( 10 );
    
    private final WeakSet<Listener> listeners = new WeakSet<Listener>( 2 );
    
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    
    private Comparator<Task> comparator;
    
    /** Creates a new instance of TaskList */
    public TaskList() {
        sortedTasks = new TreeSet<Task>(getComparator());
    }
    
    void setTasks( PushTaskScanner scanner, FileObject resource, List<? extends Task> tasks, TaskFilter filter ) throws IOException {
        lock.writeLock().lock();
        
        List<Task> removed = clear( scanner, resource );
        
        Set<Task> tasksToAdd = null;
        int currentCount = countTasks( scanner );
        for( Task t : tasks ) {
            if( filter.accept( t ) && !filter.isTaskCountLimitReached(currentCount) ) {
                currentCount++;
                
                if( sortedTasks.contains( t ) || (tasksToAdd != null && tasksToAdd.contains( t ) ) )
                    continue;
                
                if( null == tasksToAdd )
                    tasksToAdd = new HashSet<Task>( tasks.size() );
                
                List<Task> scannerTasks = pushScanner2tasks.get( scanner );
                if( null == scannerTasks ) {
                    scannerTasks = new ArrayList<Task>();
                    pushScanner2tasks.put( scanner, scannerTasks );
                }
                
                TaskGroup group = Accessor.getGroup( t );
                List<Task> groupTasks = group2tasks.get( group );
                if( null == groupTasks ) {
                    groupTasks = new ArrayList<Task>();
                    group2tasks.put( group, groupTasks );
                }

                tasksToAdd.add( t );
                scannerTasks.add( t );
                groupTasks.add( t );
            }
        }
        if( null != tasksToAdd ) {
            addTasks( tasksToAdd );
        }
        
        lock.writeLock().unlock();
        
        if( null != removed && !removed.isEmpty() )
            fireTasksRemoved( removed );
        if( null != tasksToAdd && !tasksToAdd.isEmpty() )
            fireTasksAdded(new ArrayList(tasksToAdd));
    }
    
    void clear( PushTaskScanner scanner ) {
        lock.writeLock().lock();
        List<Task> toRemove = pushScanner2tasks.get( scanner );
        pushScanner2tasks.remove( scanner );
        if( null != toRemove ) {
            for( List<Task> groupTasks : group2tasks.values() ) {
                groupTasks.removeAll( toRemove );
            }
            removeTasks( toRemove );
        }
        lock.writeLock().unlock();
        
        if( null != toRemove && !toRemove.isEmpty() ) {
            fireTasksRemoved( toRemove );
        }
    }
    
    private int countTasks( PushTaskScanner scanner ) {
        List<Task> tasks = pushScanner2tasks.get( scanner );
        return null == tasks ? 0 : tasks.size();
    }
    
    private List<Task> clear( PushTaskScanner scanner, FileObject resource ) {
        Set<Task> toRemove = null;
        List<Task> tasks = pushScanner2tasks.get( scanner );
        if( null != tasks ) {
            if( null == resource ) {
                toRemove = new HashSet<Task>();
                toRemove.addAll(tasks);
            } else {
                for( Task t : tasks ) {
                    if( resource.equals( Accessor.getFile( t ) ) ) {
                        if( null == toRemove )
                            toRemove = new HashSet<Task>();
                        toRemove.add( t );
                    }
                }
            }
        }
        
        if( null != toRemove ) {
            removeTasks( toRemove );
            tasks.removeAll( toRemove );
            for( List<Task> groupTasks : group2tasks.values() ) {
                groupTasks.removeAll( toRemove );
            }
        }
        return toRemove == null ? null : new LinkedList(toRemove);
    }
    
    void update( FileTaskScanner scanner, FileObject resource, List<Task> newTasks, TaskFilter filter ) {
        lock.writeLock().lock();
        
        List<Task> removed = clear( scanner, resource );

        Set<Task> tasksToAdd = new HashSet<Task>(newTasks.size());
        for( Task t : newTasks ) {
            if( sortedTasks.contains( t ) || tasksToAdd.contains( t ) )
                continue;
            if( !filter.isTaskCountLimitReached( countTasks( scanner ) ) && filter.accept( t ) ) {
                List<Task> scannerTasks = fileScanner2tasks.get( scanner );
                if( null == scannerTasks ) {
                    scannerTasks = new ArrayList<Task>();
                    fileScanner2tasks.put( scanner, scannerTasks );
                }
                TaskGroup group = Accessor.getGroup( t );
                List<Task> groupTasks = group2tasks.get( group );
                if( null == groupTasks ) {
                    groupTasks = new ArrayList<Task>();
                    group2tasks.put( group, groupTasks );
                }
                scannerTasks.add( t );
                groupTasks.add( t );
                tasksToAdd.add( t );
            }
        }
        if( !tasksToAdd.isEmpty() ) {
            addTasks( tasksToAdd );
        }

        lock.writeLock().unlock();

        if( null != removed && !removed.isEmpty() )
            fireTasksRemoved( removed );
        if( !tasksToAdd.isEmpty() )
            fireTasksAdded(new ArrayList<Task>(tasksToAdd));
    }
    
    public int size() {
        int retValue = 0;
        lock.readLock().lock();
        retValue = sortedTasks.size();
        lock.readLock().unlock();
        return retValue;
    }
    
    public List<? extends Task> getTasks() {
        lock.readLock().lock();
        try {
            return new ArrayList<Task>( sortedTasks );
        } finally {
            lock.readLock().unlock();
        }
    }
    
    int countTasks( FileTaskScanner scanner ) {
        List<Task> tasks = fileScanner2tasks.get( scanner );
        return null == tasks ? 0 : tasks.size();
    }
    
    public int countTasks( TaskGroup group ) {
        List<Task> groupTasks = group2tasks.get( group );
        return null == groupTasks ? 0 : groupTasks.size();
    }
    
    public Task getTask( int index ) {
        Task retValue = null;
        lock.readLock().lock();
        if( index >= 0 && index < sortedTasks.size() )
            retValue = getTasksList().get( index );
        lock.readLock().unlock();
        return retValue;
    }

    void clear( FileTaskScanner scanner ) {
        lock.writeLock().lock();
        List<Task> toRemove = fileScanner2tasks.get( scanner );
        fileScanner2tasks.remove( scanner );
        if( null != toRemove ) {
            for( List<Task> groupTasks : group2tasks.values() ) {
                groupTasks.removeAll( toRemove );
            }
            removeTasks( toRemove );
        }
        lock.writeLock().unlock();
        
        if( null != toRemove && !toRemove.isEmpty() ) {
            fireTasksRemoved( toRemove );
        }
    }
    
    void clear( FileTaskScanner scanner, FileObject... resources ) throws IOException {
        lock.readLock().lock();
        ArrayList<Task> toRemove = null;
        List<Task> tasks = fileScanner2tasks.get( scanner );
        if( null != tasks ) {
            for( Task t : tasks ) {
                for( FileObject rc : resources ) {
                    if( rc.equals( Accessor.getFile( t ) ) ) {
                        if( null == toRemove )
                            toRemove = new ArrayList<Task>( resources.length );
                        toRemove.add( t );
                    }
                }
            }
        }
        lock.readLock().unlock();
        
        if( null != toRemove && !toRemove.isEmpty() ) {
            lock.writeLock().lock();
            removeTasks( toRemove );
            tasks.removeAll( toRemove );
            for( List<Task> groupTasks : group2tasks.values() ) {
                groupTasks.removeAll( toRemove );
            }
            lock.writeLock().unlock();
            
            fireTasksRemoved( toRemove );
        }
    }
    
    private List<Task> clear( FileTaskScanner scanner, FileObject resource ) {
        List<Task> tasks = fileScanner2tasks.get( scanner );
        if( null == tasks )
            return null;
        Set<Task> toRemove = null;
        for( Task t : tasks ) {
            if( resource.equals( Accessor.getFile( t ) ) ) {
                if( null == toRemove )
                    toRemove = new HashSet<Task>();
                toRemove.add( t );
            }
        }
        
        if( null != toRemove ) {
            removeTasks( toRemove );
            tasks.removeAll( toRemove );
            for( List<Task> groupTasks : group2tasks.values() ) {
                groupTasks.removeAll( toRemove );
            }
        }
        return toRemove == null ? null : new LinkedList(toRemove);
    }
    
    void clear( FileObject resource ) {
        List<Task> toRemove = null;

        lock.writeLock().lock();

        for( List<Task> scannerTasks : fileScanner2tasks.values() ) {
            for( Task t : scannerTasks ) {
                if( resource.equals( Accessor.getFile(t) ) ) {
                    if( null == toRemove )
                        toRemove = new LinkedList<Task>();
                    toRemove.add( t );
                }
            }
        }

        if( null != toRemove ) {
            removeTasks( toRemove );
            for( List<Task> scannerTasks : fileScanner2tasks.values() ) {
                scannerTasks.removeAll( toRemove );
            }
            for( List<Task> groupTasks : group2tasks.values() ) {
                groupTasks.removeAll( toRemove );
            }
        }

        lock.writeLock().unlock();

        if( null != toRemove ) {
            fireTasksRemoved( toRemove );
        }
    }

    void clear() {
        lock.writeLock().lock();
        sortedTasks.clear();
        tasksList = null; 
        fileScanner2tasks.clear();
        pushScanner2tasks.clear();
        group2tasks.clear();
        lock.writeLock().unlock();
        fireCleared();
    }

    void clearDeletedFiles() {
        lock.writeLock().lock();
        LinkedList<Task> toRemove = new LinkedList<Task>();
        for( Task t : sortedTasks ) {
            FileObject fo = Accessor.getFile(t);
            if( null != fo && !fo.isValid() )
                toRemove.add(t);
            }

        if( !toRemove.isEmpty() ) {
            removeTasks( toRemove );
            for( List<Task> scannerTasks : fileScanner2tasks.values() ) {
                scannerTasks.removeAll( toRemove );
            }
            for( List<Task> groupTasks : group2tasks.values() ) {
                groupTasks.removeAll( toRemove );
            }
        }

        lock.writeLock().unlock();

        if( !toRemove.isEmpty() ) {
            fireTasksRemoved( toRemove );
        }
    }
    
    public void addListener( Listener l ) {
        synchronized( listeners ) {
            listeners.add( l );
        }
    }
    
    public void removeListener( Listener l ) {
        synchronized( listeners ) {
            listeners.remove( l );
        }
    }
    
    public int indexOf( Task t ) {
        lock.readLock().lock();
        int idx = getTasksList().indexOf(t);
        lock.readLock().unlock();
        return idx;
    }
    
    private Comparator<Task> getComparator() {
        if( null == comparator )
            comparator = TaskComparator.getDefault();
        return comparator;
    }
    
    public void setComparator( Comparator<Task> comparator ) {
        if( getComparator().equals( comparator ) ) {
            return;
        }
        
        lock.writeLock().lock();
        
        this.comparator = comparator;
        TreeSet<Task> s = sortedTasks;
        sortedTasks = new TreeSet<Task>(comparator);
        addTasks(s);
        
        lock.writeLock().unlock();
    }
    
    private void fireTasksAdded( List<Task> tasks ) {
        TaskList.Listener[] tmp; 
        synchronized( listeners ) {
            tmp = listeners.toArray(new TaskList.Listener[listeners.size()]);
        }
        for ( Listener l : tmp ) {
            l.tasksAdded( tasks );
        }
    }
    
    private void fireTasksRemoved( List<Task> tasks ) {
        TaskList.Listener[] tmp; 
        synchronized( listeners ) {
            tmp = listeners.toArray(new TaskList.Listener[listeners.size()]);
        }
        for ( Listener l : tmp ) {
            l.tasksRemoved( tasks );
        }
    }
    
    private void fireCleared() {
        TaskList.Listener[] tmp; 
        synchronized( listeners ) {
            tmp = listeners.toArray(new TaskList.Listener[listeners.size()]);
        }
        for( Listener l : tmp) {
            l.cleared();
        }
    }
    
    private List<Task> getTasksList() {
        if(tasksList == null) {
            tasksList = new ArrayList<Task>(sortedTasks);
        }
        return tasksList;
    }
    
    private void addTasks(Collection<Task> tasksToAdd) {
        sortedTasks.addAll( tasksToAdd );
        tasksList = null; 
    }
    
    private void removeTasks(Collection<Task> toRemove) {
        sortedTasks.removeAll( toRemove );
        tasksList = null; 
    }    
    
    public static interface Listener {
        void tasksAdded( List<? extends Task> tasks );
        void tasksRemoved( List<? extends Task> tasks );
        void cleared();
    }
}
