/*******************************************************************************
 * Copyright (c) 2007, 2008 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;

/**
 * 
 */
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");
		}
	}

}
