import java.util.ArrayList;
import java.util.List;

/** The contact class will store one name and a List of Address. The first Address in the list is the
 *  primary address that is used for the contact.
 * @author Aaron Braskin
 * @version March 24th, 2015
 */
public class Contact implements Comparable<Contact> {
	// Instance Variables
	private Name thePerson;
	private List<Address> theAddresses;

	/** The default constructor will instantiate a new <code>Name</code> object using the default constructor
	 *  of the Name class and then instantiate a new <code>ArrayList</code> of <code>Address</code>.
	 *  Finally, a new <code>Address</code> object will be instantiated using the default constructor for the
	 *  Address class.
	 */
	public Contact() {
		thePerson=new Name();		
		Address address=new Address();
		theAddresses=new ArrayList<Address>();
		theAddresses.add(address);
	}
	/** This overloaded constructor takes a <code>Name</code> object and an <code>Address</code> object as parameters.
	 *  These are then used to instantiate <em>new</em> <code>Name</code> and <code>Address</code> objects.
	 *  Next, it instantiates a new <code>ArrayList</code> of <code>Address</code> and then set the contact's fields
	 *  using the newly instantiated objects.
	 *  If <code>setPerson</code> or <code>setAddress</code>is <code>null</code> then create a new object using the
	 *  respective default constructor instead.
	 * @param setPerson the <code>Name</code> to be copied to the new contact
	 * @param setAddress the <code>Address</code> to be copied to the new contact
	 */
	public Contact(Name setPerson, Address setAddress) {
		if (setPerson!=null) {
			String firstName=setPerson.getFirst();
			String lastName=setPerson.getLast();
			thePerson=new Name(firstName,lastName);
		} else {
			thePerson=new Name();
		}
		Address anAddress;
		if (setAddress!=null) {
			String street=setAddress.getStreet();
			String city=setAddress.getCity();
			String state=setAddress.getState();
			String zip=setAddress.getZip();
			anAddress=new Address(street, city, state, zip);
		} else {
			anAddress=new Address();
		}
		theAddresses=new ArrayList<Address>();		
		theAddresses.add(anAddress);
	}
	/** Returns the name in First Last format with the primary address on the following two lines
	 * @return the Name and primary address
	 */
	public String toString() {
		return thePerson.toString()+"\n"+getPrimaryAddress();
	}
	/** Sets the first and last name if <code>setPerson</code> is not <code>null</code>*/
	public void setPerson(Name setPerson) {
		if (setPerson!=null) {
			String firstName=setPerson.getFirst();
			String lastName=setPerson.getLast();
			thePerson=new Name(firstName,lastName);
		}		
	}
	/** Gets the contact's name 
	 * @return the contacts name
	 */
	public String getName() {
		return thePerson.toString();
	}
	/** Gets the contact's name in last name first format
	 * @return the contacts last name, first name
	 */
	public String getLastNameFirst() {
		return thePerson.getLastNameFirst();
	}
	/** Returns this contacts primary address (the first one created unless it has been changed)
	 * @return the primary address for this contact
	 */
	public String getPrimaryAddress() {
		Address primaryAddress=theAddresses.get(0);
		return primaryAddress.toString();
	}
	/** Compares to <code>Contact</code> objects using the names in last, first format
	 * @param otherContact
	 * @return 	a negative integer, zero, or a positive integer as this object is less than, equal to, or
	 * greater than the specified object.
	 */
	public int compareTo(Contact otherContact) {
		String myLastFirst=thePerson.getLastNameFirst();
		String otherLastFirst=otherContact.getLastNameFirst();
		return myLastFirst.compareTo(otherLastFirst);
	}
	/** Adds the new address if <code>anotherAddress</code> is not <code>null</code> by creating a copy
	 * of <code>anotherAddress</code>
	 * @param anotherAddress the address to add
	 * @param isPrimary if true, make the new address the primary address
	 */
	public void addAddress(Address anotherAddress, boolean isPrimary) {
		if (anotherAddress!=null) {
			String street=anotherAddress.getStreet();
			String city=anotherAddress.getCity();
			String state=anotherAddress.getState();
			String zip=anotherAddress.getZip();
			Address addressToAdd=new Address(street, city, state, zip);
			if (isPrimary) {
				theAddresses.add(0,addressToAdd);
			} else {
				theAddresses.add(addressToAdd);
			}
		}
	}
	/** If the <code>addressIndex</code> is valid, it makes the primary address the one at address index
	 * 
	 * @param addressIndex the index of the new primary address
	 * @return <code>true</code> if a new address has been made the primary address
	 */
	public boolean setPrimaryAddress(int addressIndex) {
		// 1. Return false if addressIndex is not valid
		if (addressIndex<0 || addressIndex>=theAddresses.size()) return false;
		// 2. Set the address at index 0 to be the address at addressIndex, storing the address originally there
		Address oldPrimary=theAddresses.set(0, theAddresses.get(addressIndex));
		// 3. Put the address that was at index 0 back into the list
		theAddresses.set(addressIndex, oldPrimary);
		// 4. Return true
		return true;
	}
	/** Returns the address at the specified index if the index is valid, otherwise it returns the primary
	 * address
	 * @param addressIndex the index of the address to return
	 * @return the <code>Address</code> at <code>addressIndex</code>
	 */
	public String getAddress(int addressIndex) {
		// 1. Return the primary address if addressIndex is not valid
		if (addressIndex<0 || addressIndex>=theAddresses.size()) return getPrimaryAddress();
		// 2. Return the address at addressIndex
		Address theAddress=theAddresses.get(addressIndex);
		return theAddress.toString();
	}
	/** Removes the address at <code>addressIndex</code> if it is not the primary address and it is a valid index
	 * @param addressIndex the index of the address to be removed
	 * @return <code>true</code> if the address was removed
	 */
	public boolean removeAddress(int addressIndex) {
		// 1. Return false if addressIndex is not valid
		if (addressIndex<1 || addressIndex>=theAddresses.size()) return false;
		// 2. Remove the address at addressIndex from the list
		theAddresses.remove(addressIndex);
		// 3. Return true
		return true;
	}
	/** Returns a String where each address associate with this Contact is in two consecutive lines with the
	 * primary address listed first.
	 * @return all the addresses for the contact with the primary address first
	 */
	public String getAllAddresses() {
		// 1. Create an accumulator String
		String s="";
		// 2. Use a loop to concatenate each address from the list with a newline after all but the last one
		for (int i=0; i<theAddresses.size(); i++) {
			Address address=theAddresses.get(i);
			s+=address.toString();
			if (i<theAddresses.size()-1) s+="\n";
		}
		// 3. Return the accumulator String
		return s;
	}
	/** Returns true if the Names are the same
	 * @return <code>true</code> if <code>otherObject</code> is also a contact and the names are the same.
	 */
	public boolean equals(Object otherObject) {
		if (otherObject instanceof Contact) {
			Contact otherContact=(Contact)otherObject;
			return this.thePerson.equals(otherContact.thePerson);
		}
		return super.equals(otherObject);
	}
}