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

import gov.va.vinci.dart.biz.DataSource;
import gov.va.vinci.dart.biz.OperationalRequest;
import gov.va.vinci.dart.biz.OperationalStudy;
import gov.va.vinci.dart.biz.Person;
import gov.va.vinci.dart.biz.RequestStatus;
import gov.va.vinci.dart.biz.Review;
import gov.va.vinci.dart.common.exception.ObjectNotFoundException;
import gov.va.vinci.dart.common.exception.ValidationException;
import gov.va.vinci.dart.db.OperationalRequestDAO;
import gov.va.vinci.dart.service.DartObjectFactory;

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

public class OperationalRequestDAOMock implements OperationalRequestDAO {

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

		initializeRequestHash();

		// allocate a new id
		DartObjectFactory.getInstance().getRequestDAO().save(request);
	
//		if (request.getReviews() == null) {
		if (request.getAllReviews() == null) {	//Note:  OperationalRequest has no intermediate reviews
			request.setReviews(new HashSet<Review>());
		}
		
		if (request.getDataSources() == null) {
			request.setDataSources(new HashSet<DataSource>());
		}
		
		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 OperationalRequest findById(int requestId) throws ObjectNotFoundException {
		initializeRequestHash();
		
		return IDHash.get(requestId);
	}

	@Override
	public List<OperationalRequest> listByActivityId(int activityId) {
		initializeRequestHash();

		List<OperationalRequest> result = new ArrayList<OperationalRequest>();
		
		for (Integer id : IDHash.keySet()) {
			OperationalRequest req = IDHash.get(id);
			if (req.getActivity().getId() == activityId) {
				result.add(req);
			}
		}
		
		return result;
	}

	@Override
	public List<OperationalRequest> listByRequestor(int requestorId) {
		initializeRequestHash();

		List<OperationalRequest> result = new ArrayList<OperationalRequest>();
		
		for (Integer id : IDHash.keySet()) {
			OperationalRequest req = IDHash.get(id);
			if (req.getRequestor().getId() == requestorId) {
				result.add(IDHash.get(id));
			}
		}
		
		return result;
	}

	@Override
	public List<OperationalRequest> listAll() {
		initializeRequestHash();

		List<OperationalRequest> result = new ArrayList<OperationalRequest>();
		
		if (IDHash.size() > 0) {
			for (Integer id : IDHash.keySet()) {
				result.add(IDHash.get(id));
			}
		}
		
		return result;
	}

	@Override
	public List<OperationalRequest> listRecentByRequestor(int requestorId,
			int maxResults) {
		initializeRequestHash();

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

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

	private boolean nameMatch(final OperationalRequest 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<OperationalRequest> listAllButInitiated() {
		initializeRequestHash();

		List<OperationalRequest> result = new ArrayList<OperationalRequest>();
		
		for (Integer id : IDHash.keySet()) {
			OperationalRequest req = IDHash.get(id);
			try {
				if (req.getStatus().getId() != RequestStatus.INITIATED.getId()) {	//use the top-level status
					result.add(IDHash.get(id));
				}
			}
			catch (ObjectNotFoundException e) {
				e.printStackTrace();
			}
		}
		
		return result;
	}

	@Override
	public List<OperationalRequest> listAllSubmitted() {
		initializeRequestHash();

		List<OperationalRequest> result = new ArrayList<OperationalRequest>();
		
		for (Integer id : IDHash.keySet()) {
			OperationalRequest 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 OperationalRequest findMostRecentAmendment(int headId) {
		initializeRequestHash();

		int maxId = -1;
		
		for (Integer id : IDHash.keySet()) {
			OperationalRequest 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<OperationalStudy> activityList = DartObjectFactory.getInstance().getOperationalStudyDAO().listAll();
		OperationalStudy activity = activityList.get(0);
		
		// create request 1 so we'll have something to work with
		OperationalRequest req = OperationalRequest.create("test request 1", pers, activity, "DNS");
	}

}
