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

import java.util.ArrayList;
import java.util.Date;
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.common.exception.ValidationException;
import gov.va.vinci.dart.biz.DartRequest;
import gov.va.vinci.dart.biz.DataSource;
import gov.va.vinci.dart.biz.Participant;
import gov.va.vinci.dart.biz.Person;
import gov.va.vinci.dart.biz.RequestStatus;
import gov.va.vinci.dart.biz.ResearchStudy;
import gov.va.vinci.dart.db.DartRequestDAO;
import gov.va.vinci.dart.service.DartObjectFactory;

public class DartRequestDAOMock implements DartRequestDAO {

	private static boolean initialized = false;
	private static HashMap<Integer,DartRequest> IDHash = new HashMap<Integer,DartRequest>();
	
	@Override
	public void save(final DartRequest request) {
		if (request == null) {
			throw new IllegalArgumentException();
		}

		initializeRequestHash();

		// allocate a new id
		DartObjectFactory.getInstance().getRequestDAO().save(request);
	
		if (request.getDataSources() == null) {
			request.setDataSources(new HashSet<DataSource>());
		}
		
		// it looks like Hibernate automatically manages this for us.
		if (request.getActivity() != null && request.getActivity().getRequests() != null && request.getActivity().getRequests().contains(request) == false) {
			request.getActivity().getRequests().add(request);
		}

		IDHash.put(request.getId(), request);
	}

	@Override
	public DartRequest findById(int requestId) throws ObjectNotFoundException {
		initializeRequestHash();
		
		return IDHash.get(requestId);
	}

	@Override
	public List<DartRequest> listByActivityId(int activityId) {
		initializeRequestHash();
		
		List<DartRequest> result = new ArrayList<DartRequest>();
		
		for (Integer id : IDHash.keySet()) {
			DartRequest req = IDHash.get(id);
			if (req.getActivity().getId() == activityId) {
				result.add(IDHash.get(id));
			}
		}
		
		return result;
	}

	@Override
	public List<DartRequest> listByRequestor(int requestorId) {
		initializeRequestHash();
		
		List<DartRequest> result = new ArrayList<DartRequest>();
		
		for (Integer id : IDHash.keySet()) {
			DartRequest req = IDHash.get(id);
			if (req.getRequestor().getId() == requestorId) {
				result.add(IDHash.get(id));
			}
		}
		
		return result;
	}

	@Override
	public List<DartRequest> listAll() {
		initializeRequestHash();
		
		List<DartRequest> result = new ArrayList<DartRequest>();
		
		for (Integer id : IDHash.keySet()) {
			result.add(IDHash.get(id));
		}
		
		return result;
	}

	@Override
	public List<DartRequest> listRecentByRequestor(int requestorId,
			int maxResults) {
		initializeRequestHash();
		
		List<DartRequest> result = new ArrayList<DartRequest>();
		int count = 0;
		
		for (Integer id : IDHash.keySet()) {
			
			DartRequest req = IDHash.get(id);
			if (req.getRequestor().getId() == requestorId) {
				if (count++ > maxResults) {
					break;
				}
				result.add(IDHash.get(id));
			}
		}
		
		return result;
	}

	@Override
	public List<DartRequest> listByName(int requestorId, String key) {
		initializeRequestHash();
		
		List<DartRequest> result = new ArrayList<DartRequest>();
		
		for (Integer id : IDHash.keySet()) {
			DartRequest req = IDHash.get(id);
			if (req.getRequestor().getId() == requestorId && nameMatch(req, key)) {
				result.add(IDHash.get(id));
			}
		}
		
		return result;
	}

	private boolean nameMatch(final DartRequest req, final String key) {
		if (req.getName() != null && req.getName().indexOf(key) > 0) {
			return true;
		}
		
		if (req.getDescription() != null && req.getDescription().indexOf(key) > 0) {
			return true;
		}

		if (req.getTrackingNumber() != null && req.getTrackingNumber().indexOf(key) > 0) {
			return true;
		}

		return false;
	}
	
	@Override
	public List<DartRequest> listAllButInitiated() {
		initializeRequestHash();
		
		List<DartRequest> result = new ArrayList<DartRequest>();
		
		for (Integer id : IDHash.keySet()) {
			DartRequest req = IDHash.get(id);
			try {
				if (req.getStatus().getId() != RequestStatus.INITIATED.getId()) {
					result.add(IDHash.get(id));
				}
			}
			catch (ObjectNotFoundException e) {
				e.printStackTrace();
			}
		}
		
		return result;
	}

	@Override
	public List<DartRequest> listAllSubmitted() {
		initializeRequestHash();
		
		List<DartRequest> result = new ArrayList<DartRequest>();
		
		for (Integer id : IDHash.keySet()) {
			DartRequest req = IDHash.get(id);
			try {
				if (req.getStatus().getId() == RequestStatus.SUBMITTED.getId()) {	//use the top-level status
					result.add(IDHash.get(id));
				}
				else if (req.getStatus().getId() == RequestStatus.CHANGE_REQUESTED.getId()) {
					result.add(IDHash.get(id));
				}
			}
			catch (ObjectNotFoundException e) {
				e.printStackTrace();
			}
		}
		
		return result;
	}

	@Override
	public DartRequest findMostRecentAmendment(int headId) {
		initializeRequestHash();
		
		int maxId = -1;
		
		for (Integer id : IDHash.keySet()) {
			DartRequest req = IDHash.get(id);
			if (req.isAmendment() == true && req.getHeadId() == headId) {
				if (req.getId() > maxId) {
					maxId = req.getId();
				}
			}
		}

		if (maxId > 0) {
			return IDHash.get(maxId);
		}
		
		return null;
	}

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

//		try {
//			initializeRequestHash0();
//		}
//		catch (ObjectNotFoundException e) {
//			e.printStackTrace();
//		}
//		catch (ValidationException e) {
//			e.printStackTrace();
//		}
	}
	
	private void initializeRequestHash0() throws ValidationException, ObjectNotFoundException{
		
		Person pers = DartObjectFactory.getInstance().getPersonDAO().findById(1004);
		List<ResearchStudy> activityList = DartObjectFactory.getInstance().getResearchStudyDAO().listAll();
		ResearchStudy activity = activityList.get(0);
		
		// create request 1 so we'll have something to work with
		DartRequest req = DartRequest.create("test request 1", new Date(), new Date(), pers, activity, "vhaislduboij");
		
		req.setPrimaryLocation(pers.getLocation());
		
		// and that needs a primary investigator
		Participant part = Participant.create(pers, req, pers.getLocation(), true, true, true, true);
		req.getParticipants().add(part);
		
	}

}
