/*
 * Created on 1 Nov 2006
 * Created by Paul Gardner
 * Copyright (C) Azureus Software, Inc, All Rights Reserved.
 *
 * 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 org.gudy.azureus2.core3.util;

import java.lang.ref.WeakReference;
import java.util.*;

public class 
DebugWeakList 
{
	final static boolean DEBUG = Constants.isCVSVersion();
	
	private String		name;
	private List		list;
	
	public
	DebugWeakList(
		String	_name )
	{
		name	= _name;
		list	= new ArrayList();
	}
	
	public
	DebugWeakList(
		String			_name,
		DebugWeakList	l )
	{
		name	= _name;
		list 	= new ArrayList( l.list );
	}
	
	public void
	add(
		Object		obj )
	{
		if ( DEBUG ){
		
			list.add( new Object[]{ obj.getClass(), new WeakReference( obj )});
			
		}else{
			
			list.add( obj );
		}
	}
	
	public void
	remove(
		Object		obj )
	{
		if ( DEBUG ){

			Iterator	it = list.iterator();
			
			while( it.hasNext()){
				
				Object[]	entry  = (Object[])it.next();
				
				WeakReference	wr = (WeakReference)entry[1];
				
				Object	target = wr.get();
				
				if ( target == null ){
					
					it.remove();
					
					logRemoved((Class)entry[0]);
					
				}else if ( target == obj ){
					
					it.remove();
					
					return;
				}
			}
		}else{
			
			list.remove( obj );
		}
	}
	
	public boolean
	contains(
		Object	obj )
	{
		if ( DEBUG ){

			Iterator	it = list.iterator();
			
			while( it.hasNext()){
				
				Object[]	entry  = (Object[])it.next();
				
				WeakReference	wr = (WeakReference)entry[1];
				
				Object	target = wr.get();
				
				if ( target == null ){
					
					it.remove();
					
					logRemoved((Class)entry[0]);
					
				}else if ( target == obj ){
					
					return( true );
				}
			}
			
			return( false );
		}else{
			
			return( list.contains( obj ));
		}
	}
	
	protected void
	logRemoved(
		Class	cla )
	{
		Debug.out( "Object '" + cla + "' was not removed correctly from " + name );
	}
	
	public Iterator
	iterator()
	{
		if ( DEBUG ){

			return( new WeakListIterator());
			
		}else{
			
			return( list.iterator());
		}
	}
	
	public int
	estimatedSize()
	{
		return( list.size());
	}
	
	protected class
	WeakListIterator
		implements Iterator
	{
		private Iterator	it = list.iterator();
		
		private Object	pending_result;
		private Object	last_result;
		
		public boolean
		hasNext()
		{
			if ( pending_result != null ){
				
				return( true );
			}
			
			while( it.hasNext()){
									
				Object[]	entry  = (Object[])it.next();
				
				WeakReference	wr = (WeakReference)entry[1];
				
				Object	target = wr.get();
				
				if ( target == null ){
					
					it.remove();
					
					logRemoved((Class)entry[0]);
					
				}else{
					
					pending_result = target;
					
					return( true );
				}
			}
			
			return( false );
		}
		
		public Object
		next()
		
			throws NoSuchElementException
		{
			if ( pending_result == null ){
				
				hasNext();
			}
			
			if ( pending_result == null ){
				
				throw( new NoSuchElementException());
			}
			
			last_result = pending_result;
			
			pending_result = null;
			
			return( last_result );
		}
		
		public void
		remove()
		{
			Object	lr = last_result;
			
			if ( lr == null ){
				
				throw( new NoSuchElementException());
			}
			
			last_result	= null;
			
			if ( pending_result == null ){
				
				it.remove();
				
			}else{
			
					// has next has skipped on beyond last result, need to manually fix up...
				
				Iterator	temp_it = list.iterator();
				
				while( temp_it.hasNext()){
					
					Object[]	entry  = (Object[])temp_it.next();
					
					WeakReference	wr = (WeakReference)entry[1];
					
					Object	target = wr.get();

					if ( target == lr ){
						
						it = temp_it;
						
						it.remove();
						
						return;
					}
				}
				
					// not found (Garbage collected), nothing to do	
			}
		}
	}
}
