package gov.va.vinci.dart.db.mock;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

import gov.va.vinci.dart.common.exception.ObjectNotFoundException;
import gov.va.vinci.dart.biz.Group;
import gov.va.vinci.dart.biz.Location;
import gov.va.vinci.dart.biz.Person;
import gov.va.vinci.dart.biz.PersonGroup;
import gov.va.vinci.dart.biz.PersonTask;
import gov.va.vinci.dart.biz.Role;
import gov.va.vinci.dart.db.PersonDAO;

public class PersonDAOMock implements PersonDAO {
	private static final HashMap<Integer,Person> IDHash = new HashMap<Integer,Person>();
	private static final HashMap<String,Person> NameHash = new HashMap<String,Person>();

	private static boolean initialized = false;
	private static int idCounter = 3;


	@Override
	public Person findById(int personId) throws ObjectNotFoundException {
		initializePersonHash();

		Person result = IDHash.get(personId);
		
		if (result == null) {
			throw new ObjectNotFoundException();
		}

		return result;
	}

	@Override
	public Person findByName(String name) throws ObjectNotFoundException {
		initializePersonHash();

		Person result = NameHash.get(name);
		
		if (result == null) {
			throw new ObjectNotFoundException();
		}

		return result;
	}

	public Person findByNameCaseInsensitive(String name) throws ObjectNotFoundException {
		initializePersonHash();

		for (Integer id: IDHash.keySet()) {
			Person pers = IDHash.get(id);
			if (pers.getName().equalsIgnoreCase(name)) {
				return pers;
			}
		}

		throw new ObjectNotFoundException();
	}

	@Override
	public List<Person> listAll() {
		List<Person> result = new ArrayList<Person>();
		
		initializePersonHash();

		for (Integer id: IDHash.keySet()) {
			result.add(IDHash.get(id));
		}

		return result;	
	}

	@Override
	public List<Person> list(String term) {
		initializePersonHash();

		// "from Person where name like :term or description like :term or fullName like :term"
		
		List<Person> result = new ArrayList<Person>();
		
		for (Integer id: IDHash.keySet()) { 
			Person pers = IDHash.get(id);

			if (term != null && term.length() > 0) {
				if (pers.getName() != null && pers.getName().indexOf(term) >= 0) {
					result.add(pers);
				}
				else if (pers.getDescription() != null && pers.getDescription().indexOf(term) >= 0) {
					result.add(pers);
				}
				else if (pers.getFullName() != null && pers.getFullName().indexOf(term) >= 0) {
					result.add(pers);
				}
			}
			else {
				// no term passed returns all persons
				result.add(pers);  
			}
		}
		
		return result;	
	}

	@Override
	public List<Person> listAllWithRole(int roleId) {
		List<Person> result = new ArrayList<Person>();
		
		initializePersonHash();

		for (Integer id: IDHash.keySet()) {
			Person pers = IDHash.get(id);
			
			for (Role role : pers.getRoles()) {
				if (roleId == role.getId()) {
					result.add(pers);
					break;
				}
			}
		}

		return result;	
	}

	@Override
	public List<Person> listByGroup(int groupId) {
		List<Person> result = new ArrayList<Person>();
		
		initializePersonHash();

		for (Integer id: IDHash.keySet()) {
			Person pers = IDHash.get(id);
			
			for (Group grp : pers.getGroups()) {
				if (groupId == grp.getId()) {
					result.add(pers);
					break;
				}
			}
		}

		return result;	
	}

	@Override
	public List<Person> listByGroupAndNotifications(int groupId) {
		List<Person> result = new ArrayList<Person>();
		
		initializePersonHash();

		for (Integer id: IDHash.keySet()) {
			Person pers = IDHash.get(id);
			
			for (PersonGroup grp : pers.getPersonGroups()) {
				if (grp != null && grp.getGroup() != null && groupId == grp.getGroup().getId()) {

					if( grp.getNotification() == true ) {
						result.add(pers);
						break;
					}//end if
				}
			}
		}

		return result;	
	}
	
	@Override
	public List<Person> listAllWithRoleAndGroup(final int roleId, final int groupId) {
		List<Person> result = new ArrayList<Person>();
		
		initializePersonHash();

		for (Integer id: IDHash.keySet()) {
			Person pers = IDHash.get(id);
			
			for( Group grp : pers.getGroups() ) {
				if( grp != null && groupId == grp.getId() ) {

					for( Role role : pers.getRoles() ) {
						if( role != null && roleId == role.getId() ) {
					
							result.add(pers);
							break;
						}
					}//end for -- role
				}
			}//end for -- group
		}//end for

		return result;	
	}
	
	@Override
	public List<Person> listAllWithRoleAndGroupAndNotifications(final int roleId, final int groupId) {
		List<Person> result = new ArrayList<Person>();
		
		initializePersonHash();

		for (Integer id: IDHash.keySet()) {
			Person pers = IDHash.get(id);
			
			for( PersonGroup grp : pers.getPersonGroups() ) {
				if( grp != null && grp.getGroup() != null && groupId == grp.getGroup().getId() ) {
					
					if( grp.getNotification() == true ) {
					
						for( Role role : pers.getRoles() ) {
							if( role != null && roleId == role.getId() ) {
						
								result.add(pers);
								break;
							}
						}//end for -- role
					}

				}
			}//end for -- group
		}//end for

		return result;	
	}
	
	
	@Override
	public synchronized void save(final Person person) {
		
		initializePersonHash();
		
		if (person.getId() == 0) {
			person.setId(idCounter++);
		}
		
		if (person.getGroups() == null) {
			person.setGroups(new HashSet<Group>());
		}
		
		if (person.getRoles() == null) {
			person.setRoles(new HashSet<Role>());
		}
		
		IDHash.put(person.getId(), person);
		NameHash.put(person.getName(), person);
	}

	private void initializePersonHash() {
		if (initialized == true) {
			return;
		}

		initialized = true;

		try {
			initializePersonHash0();
		} catch (ObjectNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private Person createPerson(final int id, final String name, final String fullName, final int locationId, final int groupId, final int roleId) throws ObjectNotFoundException {
		Person pers = new Person();
		pers.setId(id);
		pers.setName(name);
		pers.setFullName(fullName);
		pers.setLocation(Location.findById(locationId));
		
		pers.setGroups(new HashSet<Group>());
		if (groupId > 0) {
			Group grp = Group.findById(groupId);
			grp.getMembers().add(pers);
			pers.getGroups().add(grp);
		}
		
		pers.setRoles(new HashSet<Role>());
		if (roleId > 0) {
			Role role = Role.findById(roleId);
			pers.getRoles().add(role);
		}
		
		pers.setTasks(new HashSet<PersonTask>());
		
		IDHash.put(pers.getId(), pers);
		NameHash.put(pers.getName(), pers);

		return pers;
	}
	
	private void initializePersonHash0() throws ObjectNotFoundException {

		createPerson(1004, "DNS", "PII (FVFT)", 1, 1, 4);
		createPerson(1005, "DNS", "PII (FVFT)", 1, 15, 3);
		createPerson(1006, "DNS", "PII", 1, 15, 3);
		createPerson(1008, "DNS", "PII", 1, 0, 0);
		createPerson(1009, "DNS", "PII (FVFT)", 1, 0, 0);
		createPerson(1013, "ADMIN", "Administrator, Administrator", 1, 0, 0);
		createPerson(1014, "DNS", "PII (FVFT)", 1, 0, 0);
		createPerson(1016, "DNS", "PII (FVFT)", 1, 0, 0);
		createPerson(1046, "DNS", "PII(FVFT)", 1, 0, 0);
		createPerson(1050, "DNS", "PII (FVFT)", 1, 15, 3);
		createPerson(1051, "DNS", "PII (FVFT)", 1, 0, 0);
		createPerson(2005, "DNS", " PII (FVFT)", 10, 5, 1);
		createPerson(2006, "DNS", "PII (FVFT)", 8, 0, 0);
		createPerson(2007, "DNS", "PII (FVFT)", 3, 1, 4);
		createPerson(2008, "DNS", "PII (FVFT)", 106, 0, 0);
		createPerson(2009, "DNS", "PII (IGS)", 106, 0, 0);
		createPerson(2010, "DNS", "PII (FVFT)", 3, 1, 4);
		createPerson(2011, "DNS", "PII", 1, 0, 0);
		createPerson(2012, "DNS", "PII", 26, 0, 0);
		createPerson(2013, "test1", "Administrator, Administrator", 1, 0, 0);
		createPerson(3263, "DNS", "PII", 26, 0, 0);
		createPerson(4100, "DNS", "PII (FVFT)", 26, 15, 3);
        createPerson(4101, "DNS", "PII (FVFT)", 26, 0, 0);
		createPerson(1001, "DNS", "PII (FVFT)", 1, 15, 3);

	}
	
}
