/*******************************************************************************
 * Copyright (c) 2007, 2010 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0, which accompanies this distribution
 * and is available at http://www.eclipse.org/legal/epl-v10.html.
 * 
 * Contributors:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.utility.tests.internal.model.value.swing;

import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import junit.framework.TestCase;
import org.eclipse.jpt.utility.internal.CollectionTools;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.jpt.utility.internal.iterators.CloneIterator;
import org.eclipse.jpt.utility.internal.iterators.TransformationIterator;
import org.eclipse.jpt.utility.internal.model.AbstractModel;
import org.eclipse.jpt.utility.internal.model.value.CollectionAspectAdapter;
import org.eclipse.jpt.utility.internal.model.value.PropertyAspectAdapter;
import org.eclipse.jpt.utility.internal.model.value.SortedListValueModelAdapter;
import org.eclipse.jpt.utility.internal.model.value.swing.ColumnAdapter;
import org.eclipse.jpt.utility.internal.model.value.swing.TableModelAdapter;
import org.eclipse.jpt.utility.model.listener.ListChangeListener;
import org.eclipse.jpt.utility.model.listener.PropertyChangeListener;
import org.eclipse.jpt.utility.model.value.CollectionValueModel;
import org.eclipse.jpt.utility.model.value.ListValueModel;
import org.eclipse.jpt.utility.model.value.WritablePropertyValueModel;
import org.eclipse.jpt.utility.tests.internal.TestTools;

@SuppressWarnings("nls")
public class TableModelAdapterTests extends TestCase {
	private Crowd crowd;
	TableModelEvent event;

	public TableModelAdapterTests(String name) {
		super(name);
	}

	@Override
	protected void setUp() throws Exception {
		super.setUp();
		this.crowd = this.buildCrowd();
	}

	@Override
	protected void tearDown() throws Exception {
		TestTools.clear(this);
		super.tearDown();
	}

	public void testGetRowCount() throws Exception {
		TableModelAdapter<Person> tableModelAdapter =  this.buildTableModelAdapter();
		assertEquals(0, tableModelAdapter.getRowCount());
		// we need to add a listener to wake up the adapter
		tableModelAdapter.addTableModelListener(this.buildTableModelListener());
		assertEquals(this.crowd.peopleSize(), tableModelAdapter.getRowCount());
	}

	public void testGetColumnCount() throws Exception {
		TableModelAdapter<Person> tableModelAdapter =  this.buildTableModelAdapter();
		assertEquals(PersonColumnAdapter.COLUMN_COUNT, tableModelAdapter.getColumnCount());
	}

	public void testGetValueAt() throws Exception {
		TableModelAdapter<Person> tableModelAdapter =  this.buildTableModelAdapter();
		tableModelAdapter.addTableModelListener(this.buildTableModelListener());

		List<String> sortedNames = this.sortedNames();
		for (int i = 0; i < this.crowd.peopleSize(); i++) {
			assertEquals(sortedNames.get(i), tableModelAdapter.getValueAt(i, PersonColumnAdapter.NAME_COLUMN));
		}
	}

	public void testSetValueAt() throws Exception {
		TableModelAdapter<Person> tableModelAdapter =  this.buildTableModelAdapter();
		this.event = null;
		tableModelAdapter.addTableModelListener(new TestTableModelListener() {
			@Override
			public void tableChanged(TableModelEvent e) {
				TableModelAdapterTests.this.event = e;
			}
		});

		Person person = this.crowd.personNamed("Gollum");
		assertEquals(Person.EYE_COLOR_BLUE, person.getEyeColor());
		assertFalse(person.isEvil());
		assertEquals(0, person.getRank());

		for (int i = 0; i < tableModelAdapter.getRowCount(); i++) {
			if (tableModelAdapter.getValueAt(i, PersonColumnAdapter.NAME_COLUMN).equals("Gollum")) {
				tableModelAdapter.setValueAt(Person.EYE_COLOR_HAZEL, i, PersonColumnAdapter.EYE_COLOR_COLUMN);
				tableModelAdapter.setValueAt(Boolean.TRUE, i, PersonColumnAdapter.EVIL_COLUMN);
				tableModelAdapter.setValueAt(new Integer(-1), i, PersonColumnAdapter.RANK_COLUMN);
				break;
			}
		}
		assertNotNull(this.event);
		assertEquals(Person.EYE_COLOR_HAZEL, person.getEyeColor());
		assertTrue(person.isEvil());
		assertEquals(-1, person.getRank());
	}

	public void testAddRow() throws Exception {
		TableModelAdapter<Person> tableModelAdapter =  this.buildTableModelAdapter();
		this.event = null;
		tableModelAdapter.addTableModelListener(this.buildSingleEventListener());
		// add a person to the end of the list so we only trigger one event
		this.crowd.addPerson("Zzzzz");
		assertNotNull(this.event);
		assertEquals(TableModelEvent.INSERT, this.event.getType());
		assertEquals(TableModelEvent.ALL_COLUMNS, this.event.getColumn());
	}

	public void testRemoveRow() throws Exception {
		TableModelAdapter<Person> tableModelAdapter =  this.buildTableModelAdapter();
		this.event = null;
		tableModelAdapter.addTableModelListener(this.buildSingleEventListener());
		// removing a person should only trigger one event, since a re-sort is not needed
		this.crowd.removePerson(this.crowd.personNamed("Gollum"));
		assertNotNull(this.event);
		assertEquals(TableModelEvent.DELETE, this.event.getType());
		assertEquals(TableModelEvent.ALL_COLUMNS, this.event.getColumn());
	}

	public void testChangeCell() throws Exception {
		TableModelAdapter<Person> tableModelAdapter =  this.buildTableModelAdapter();
		this.event = null;
		tableModelAdapter.addTableModelListener(this.buildSingleEventListener());
		// add a person to the end of the list so we only trigger one event
		Person person = this.crowd.personNamed("Gollum");
		person.setEvil(true);
		assertNotNull(this.event);
		assertEquals(TableModelEvent.UPDATE, this.event.getType());
		assertEquals(PersonColumnAdapter.EVIL_COLUMN, this.event.getColumn());
	}

	public void testLazyListListener() throws Exception {
		TableModelAdapter<Person> tableModelAdapter =  this.buildTableModelAdapter();
		TableModelListener listener = this.buildTableModelListener();
		assertTrue(this.crowd.hasNoCollectionChangeListeners(Crowd.PEOPLE_COLLECTION));
		tableModelAdapter.addTableModelListener(listener);
		assertTrue(this.crowd.hasAnyCollectionChangeListeners(Crowd.PEOPLE_COLLECTION));
		tableModelAdapter.removeTableModelListener(listener);
		assertTrue(this.crowd.hasNoCollectionChangeListeners(Crowd.PEOPLE_COLLECTION));
	}

	public void testLazyCellListener() throws Exception {
		TableModelAdapter<Person> tableModelAdapter =  this.buildTableModelAdapter();
		TableModelListener listener = this.buildTableModelListener();
		Person person = this.crowd.personNamed("Gollum");
		assertTrue(person.hasNoPropertyChangeListeners(Person.NAME_PROPERTY));
		assertTrue(person.hasNoPropertyChangeListeners(Person.BIRTH_DATE_PROPERTY));
		assertTrue(person.hasNoPropertyChangeListeners(Person.EYE_COLOR_PROPERTY));
		assertTrue(person.hasNoPropertyChangeListeners(Person.EVIL_PROPERTY));
		assertTrue(person.hasNoPropertyChangeListeners(Person.RANK_PROPERTY));

		tableModelAdapter.addTableModelListener(listener);
		assertTrue(person.hasAnyPropertyChangeListeners(Person.NAME_PROPERTY));
		assertTrue(person.hasAnyPropertyChangeListeners(Person.BIRTH_DATE_PROPERTY));
		assertTrue(person.hasAnyPropertyChangeListeners(Person.EYE_COLOR_PROPERTY));
		assertTrue(person.hasAnyPropertyChangeListeners(Person.EVIL_PROPERTY));
		assertTrue(person.hasAnyPropertyChangeListeners(Person.RANK_PROPERTY));

		tableModelAdapter.removeTableModelListener(listener);
		assertTrue(person.hasNoPropertyChangeListeners(Person.NAME_PROPERTY));
		assertTrue(person.hasNoPropertyChangeListeners(Person.BIRTH_DATE_PROPERTY));
		assertTrue(person.hasNoPropertyChangeListeners(Person.EYE_COLOR_PROPERTY));
		assertTrue(person.hasNoPropertyChangeListeners(Person.EVIL_PROPERTY));
		assertTrue(person.hasNoPropertyChangeListeners(Person.RANK_PROPERTY));
	}

	private TableModelAdapter<Person> buildTableModelAdapter() {
		return new TableModelAdapter<Person>(this.buildSortedPeopleAdapter(), this.buildColumnAdapter()) {
			@Override
			protected PropertyChangeListener buildCellListener() {
				return this.buildCellListener_();
			}
			@Override
			protected ListChangeListener buildListChangeListener() {
				return this.buildListChangeListener_();
			}
		};
	}

	private ListValueModel<Person> buildSortedPeopleAdapter() {
		return new SortedListValueModelAdapter<Person>(this.buildPeopleAdapter());
	}

	private CollectionValueModel<Person> buildPeopleAdapter() {
		return new CollectionAspectAdapter<Crowd, Person>(Crowd.PEOPLE_COLLECTION, this.crowd) {
			@Override
			protected Iterator<Person> iterator_() {
				return this.subject.people();
			}
			@Override
			protected int size_() {
				return this.subject.peopleSize();
			}
		};
	}

	private Crowd buildCrowd() {
		Crowd result = new Crowd();
		result.addPerson("Bilbo");
		result.addPerson("Gollum");
		result.addPerson("Frodo");
		result.addPerson("Samwise");
		return result;
	}

	private ColumnAdapter buildColumnAdapter() {
		return new PersonColumnAdapter();
	}

	private TableModelListener buildTableModelListener() {
		return new TestTableModelListener();
	}

	private List<String> sortedNames() {
		return new ArrayList<String>(CollectionTools.sortedSet(this.crowd.peopleNames()));
	}

	private TableModelListener buildSingleEventListener() {
		return new TestTableModelListener() {
			@Override
			public void tableChanged(TableModelEvent e) {
				// we expect only a single event
				if (TableModelAdapterTests.this.event == null) {
					TableModelAdapterTests.this.event = e;
				} else {
					fail("unexpected event");
				}
			}
		};
	}


	// ********** classes **********

	public static class PersonColumnAdapter implements ColumnAdapter {
		public static final int COLUMN_COUNT = 7;
	
		public static final int NAME_COLUMN = 0;
		public static final int BIRTH_DATE_COLUMN = 1;
		public static final int GONE_WEST_DATE_COLUMN = 2;
		public static final int EYE_COLOR_COLUMN = 3;
		public static final int EVIL_COLUMN = 4;
		public static final int RANK_COLUMN = 5;
		public static final int ADVENTURE_COUNT_COLUMN = 6;
	
		private static final String[] COLUMN_NAMES = new String[] {
			"Name",
			"Birth",
			"Gone West",
			"Eyes",
			"Evil",
			"Rank",
			"Adventures"
		};
	
	
		public int columnCount() {
			return COLUMN_COUNT;
		}
	
		public String columnName(int index) {
			return COLUMN_NAMES[index];
		}
	
		public Class<?> columnClass(int index) {
			switch (index) {
				case NAME_COLUMN:					return Object.class;
				case BIRTH_DATE_COLUMN:			return Date.class;
				case GONE_WEST_DATE_COLUMN:	return Date.class;
				case EYE_COLOR_COLUMN:			return Object.class;
				case EVIL_COLUMN:					return Boolean.class;
				case RANK_COLUMN:					return Integer.class;
				case ADVENTURE_COUNT_COLUMN:return Integer.class;
				default: 									return Object.class;
			}
		}
	
		public boolean columnIsEditable(int index) {
			return index != NAME_COLUMN;
		}
	
		public WritablePropertyValueModel<Object>[] cellModels(Object subject) {
			Person person = (Person) subject;
			@SuppressWarnings("unchecked")
			WritablePropertyValueModel<Object>[] result = new WritablePropertyValueModel[COLUMN_COUNT];
	
			result[NAME_COLUMN] = this.buildNameAdapter(person);
			result[BIRTH_DATE_COLUMN] = this.buildBirthDateAdapter(person);
			result[GONE_WEST_DATE_COLUMN] = this.buildGoneWestDateAdapter(person);
			result[EYE_COLOR_COLUMN] = this.buildEyeColorAdapter(person);
			result[EVIL_COLUMN] = this.buildEvilAdapter(person);
			result[RANK_COLUMN] = this.buildRankAdapter(person);
			result[ADVENTURE_COUNT_COLUMN] = this.buildAdventureCountAdapter(person);
	
			return result;
		}
	
		private WritablePropertyValueModel<Object> buildNameAdapter(Person person) {
			return new PropertyAspectAdapter<Person, Object>(Person.NAME_PROPERTY, person) {
				@Override
				protected String buildValue_() {
					return this.subject.getName();
				}
				@Override
				protected void setValue_(Object value) {
					this.subject.setName((String) value);
				}
			};
		}
	
		private WritablePropertyValueModel<Object> buildBirthDateAdapter(Person person) {
			return new PropertyAspectAdapter<Person, Object>(Person.BIRTH_DATE_PROPERTY, person) {
				@Override
				protected Date buildValue_() {
					return this.subject.getBirthDate();
				}
				@Override
				protected void setValue_(Object value) {
					this.subject.setBirthDate((Date) value);
				}
			};
		}
	
		private WritablePropertyValueModel<Object> buildGoneWestDateAdapter(Person person) {
			return new PropertyAspectAdapter<Person, Object>(Person.GONE_WEST_DATE_PROPERTY, person) {
				@Override
				protected Date buildValue_() {
					return this.subject.getGoneWestDate();
				}
				@Override
				protected void setValue_(Object value) {
					this.subject.setGoneWestDate((Date) value);
				}
			};
		}
	
		private WritablePropertyValueModel<Object> buildEyeColorAdapter(Person person) {
			return new PropertyAspectAdapter<Person, Object>(Person.EYE_COLOR_PROPERTY, person) {
				@Override
				protected String buildValue_() {
					return this.subject.getEyeColor();
				}
				@Override
				protected void setValue_(Object value) {
					this.subject.setEyeColor((String) value);
				}
			};
		}
	
		private WritablePropertyValueModel<Object> buildEvilAdapter(Person person) {
			return new PropertyAspectAdapter<Person, Object>(Person.EVIL_PROPERTY, person) {
				@Override
				protected Boolean buildValue_() {
					return Boolean.valueOf(this.subject.isEvil());
				}
				@Override
				protected void setValue_(Object value) {
					this.subject.setEvil(((Boolean)value).booleanValue());
				}
			};
		}
	
		private WritablePropertyValueModel<Object> buildRankAdapter(Person person) {
			return new PropertyAspectAdapter<Person, Object>(Person.RANK_PROPERTY, person) {
				@Override
				protected Integer buildValue_() {
					return new Integer(this.subject.getRank());
				}
				@Override
				protected void setValue_(Object value) {
					this.subject.setRank(((Integer) value).intValue());
				}
			};
		}
	
		private WritablePropertyValueModel<Object> buildAdventureCountAdapter(Person person) {
			return new PropertyAspectAdapter<Person, Object>(Person.ADVENTURE_COUNT_PROPERTY, person) {
				@Override
				protected Integer buildValue_() {
					return new Integer(this.subject.getAdventureCount());
				}
				@Override
				protected void setValue_(Object value) {
					this.subject.setAdventureCount(((Integer) value).intValue());
				}
			};
		}
	
	}


	public static class Crowd extends AbstractModel {
		private final Collection<Person> people;
			public static final String PEOPLE_COLLECTION = "people";
	
		public Crowd() {
			super();
			this.people = new ArrayList<Person>();
		}
	
	
		public Iterator<Person> people() {
			return new CloneIterator<Person>(this.people) {
				@Override
				protected void remove(Person person) {
					Crowd.this.removePerson(person);
				}
			};
		}
	
		public int peopleSize() {
			return this.people.size();
		}
	
		public Person addPerson(String name) {
			this.checkPersonName(name);
			return this.addPerson(new Person(this, name));
		}
	
		private Person addPerson(Person person) {
			this.addItemToCollection(person, this.people, PEOPLE_COLLECTION);
			return person;
		}
	
		public void removePerson(Person person) {
			this.removeItemFromCollection(person, this.people, PEOPLE_COLLECTION);
		}
	
		public void removePeople(Collection<Person> persons) {
			this.removeItemsFromCollection(persons, this.people, PEOPLE_COLLECTION);
		}
	
		public void removePeople(Iterator<Person> persons) {
			this.removeItemsFromCollection(persons, this.people, PEOPLE_COLLECTION);
		}
	
		void checkPersonName(String personName) {
			if (personName == null) {
				throw new NullPointerException();
			}
			if (CollectionTools.contains(this.peopleNames(), personName)) {
				throw new IllegalArgumentException(personName);
			}
		}
	
		public Iterator<String> peopleNames() {
			return new TransformationIterator<Person, String>(this.people.iterator()) {
				@Override
				protected String transform(Person person) {
					return person.getName();
				}
			};
		}
	
		public Person personNamed(String name) {
			for (Iterator<Person> stream = this.people.iterator(); stream.hasNext(); ) {
				Person person = stream.next();
				if (person.getName().equals(name)) {
					return person;
				}
			}
			return null;
		}
	
		@Override
		public String toString() {
			return StringTools.buildToStringFor(this, String.valueOf(this.people.size()) + " people");
		}
	
	}
	
	
	public static class Person extends AbstractModel implements Comparable<Person> {
		private Crowd crowd;
		private String name;
			public static final String NAME_PROPERTY= "name";
		private Date birthDate;
			public static final String BIRTH_DATE_PROPERTY= "birthDate";
		private Date goneWestDate;
			public static final String GONE_WEST_DATE_PROPERTY= "goneWestDate";
		private String eyeColor;
			public static final String EYE_COLOR_PROPERTY= "eyeColor";
			public static final String EYE_COLOR_BLUE = "blue";
			public static final String EYE_COLOR_GREEN = "green";
			public static final String EYE_COLOR_BROWN = "brown";
			public static final String EYE_COLOR_HAZEL = "hazel";
			public static final String EYE_COLOR_PINK = "pink";
			private static Collection<String> validEyeColors;
			public static final String DEFAULT_EYE_COLOR = EYE_COLOR_BLUE;
		private boolean evil;
			public static final String EVIL_PROPERTY= "evil";
		private int rank;
			public static final String RANK_PROPERTY= "rank";
		private int adventureCount;
			public static final String ADVENTURE_COUNT_PROPERTY= "adventureCount";
	
		Person(Crowd crowd, String name) {
			super();
			this.crowd = crowd;
			this.name = name;
			this.birthDate = new Date();
			Calendar c = Calendar.getInstance();
			c.add(Calendar.YEAR, 250);
			this.goneWestDate = new Date(c.getTimeInMillis());
			this.eyeColor = DEFAULT_EYE_COLOR;
			this.evil = false;
			this.rank = 0;
			this.adventureCount = 0;
		}
	
		public static Collection<String> getValidEyeColors() {
			if (validEyeColors == null) {
				validEyeColors = buildValidEyeColors();
			}
			return validEyeColors;
		}
	
		private static Collection<String> buildValidEyeColors() {
			Collection<String> result = new ArrayList<String>();
			result.add(EYE_COLOR_BLUE);
			result.add(EYE_COLOR_GREEN);
			result.add(EYE_COLOR_BROWN);
			result.add(EYE_COLOR_HAZEL);
			result.add(EYE_COLOR_PINK);
			return result;
		}
	
		public Crowd getCrowd() {
			return this.crowd;
		}
	
		public String getName() {
			return this.name;
		}
		public void setName(String name) {
			this.crowd.checkPersonName(name);
			Object old = this.name;
			this.name = name;
			this.firePropertyChanged(NAME_PROPERTY, old, name);
		}
	
		public Date getBirthDate() {
			return this.birthDate;
		}
		public void setBirthDate(Date birthDate) {
			Object old = this.birthDate;
			this.birthDate = birthDate;
			this.firePropertyChanged(BIRTH_DATE_PROPERTY, old, birthDate);
		}
	
		public Date getGoneWestDate() {
			return this.goneWestDate;
		}
		public void setGoneWestDate(Date goneWestDate) {
			Object old = this.goneWestDate;
			this.goneWestDate = goneWestDate;
			this.firePropertyChanged(GONE_WEST_DATE_PROPERTY, old, goneWestDate);
		}
	
		public String getEyeColor() {
			return this.eyeColor;
		}
		public void setEyeColor(String eyeColor) {
			if (! getValidEyeColors().contains(eyeColor)) {
				throw new IllegalArgumentException(eyeColor);
			}
			Object old = this.eyeColor;
			this.eyeColor = eyeColor;
			this.firePropertyChanged(EYE_COLOR_PROPERTY, old, eyeColor);
		}
	
		public boolean isEvil() {
			return this.evil;
		}
		public void setEvil(boolean evil) {
			boolean old = this.evil;
			this.evil = evil;
			this.firePropertyChanged(EVIL_PROPERTY, old, evil);
		}
	
		public int getRank() {
			return this.rank;
		}
		public void setRank(int rank) {
			int old = this.rank;
			this.rank = rank;
			this.firePropertyChanged(RANK_PROPERTY, old, rank);
		}
	
		public int getAdventureCount() {
			return this.adventureCount;
		}
		public void setAdventureCount(int adventureCount) {
			int old = this.adventureCount;
			this.adventureCount = adventureCount;
			this.firePropertyChanged(ADVENTURE_COUNT_PROPERTY, old, adventureCount);
		}
	
		public int compareTo(Person p) {
			return this.name.compareToIgnoreCase(p.name);
		}
	
		@Override
		public String toString() {
			return this.name + 
						"\tborn: " + DateFormat.getDateInstance().format(this.birthDate) + 
						"\tgone west: " + DateFormat.getDateInstance().format(this.goneWestDate) + 
						"\teyes: " + this.eyeColor + 
						"\tevil: " + this.evil + 
						"\trank: " + this.rank +
						"\tadventures: " + this.adventureCount
			;
		}
	
	}


	private class TestTableModelListener implements TableModelListener {
		TestTableModelListener() {
			super();
		}
		public void tableChanged(TableModelEvent e) {
			fail("unexpected event");
		}
	}

}
