package gov.va.vss.web.interceptor;

import java.net.URL;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;

import gov.va.shared.model.Permission;
import gov.va.shared.model.Permission.PermissionType;
import gov.va.shared.model.Role.RoleType;
import gov.va.shared.model.lookup.sds.VAFacility.VAFacilityValue;
import gov.va.shared.persistence.AppUserDAO;
import gov.va.shared.persistence.lookup.sds.StateDAO;
import gov.va.shared.util.WebUtil;
import gov.va.vss.config.CommonWebConfig;
import gov.va.vss.model.facility.Facility;
import gov.va.vss.model.facility.Facility.FacilityValue;
import gov.va.vss.persistence.dao.facility.FacilityDAO;
import gov.va.vss.persistence.dao.facility.KioskDAO;
import gov.va.vss.service.VelocityService;
import gov.va.vss.util.DateUtil;
import gov.va.vss.util.context.SessionUtil;
import gov.va.vss.web.UserNotifier;

public abstract class AbstractReferenceDataInterceptor extends AbstractModelDrivenPostInterceptor {
	private static final Logger log = LoggerFactory.getLogger(AbstractReferenceDataInterceptor.class);

	public static final String ONE_TIME_USER_NOTIFICATION = "oneTimeUserNotification";

	@Autowired
	protected AppUserDAO appUserDAO;
	@Autowired
	protected FacilityDAO facilityDAO;
	@Autowired
	protected KioskDAO kioskDAO;
	@Autowired
	protected VelocityService velocityService;
	@Autowired
	protected StateDAO stateDAO;

	@Value("${session.pollingIntervalSeconds}")
	private int sessionPollingIntervalSeconds;
	@Value("${session.failedRequestsCount}")
	private int sessionFailedRequestsCount;
	@Value("${session.heartBeatTimeoutMillis}")
	private int sessionHeartBeatTimeoutMillis;
	@Value("${protocolHostnamePortOverride}")
	private String protocolHostnamePortOverride;

	@Value("${solr.baseURL}")
	private String solrBaseURL;
	@Value("${useMinifiedDependencies}")
	private String useMinifiedDependencies;
	@Value("${maxGetRequestLength}")
	private int maxGetRequestLength;

	protected abstract void addAdditionalReferenceData(HttpServletRequest request, HttpServletResponse response,
			Object handler, Map<String, Object> model) throws Exception;

	@Override
	protected final void postHandleWithValidModel(HttpServletRequest request, HttpServletResponse response,
			Object handler, Map<String, Object> model) throws Exception {

		HttpSession session = request.getSession();

		session.setAttribute("sessionPollingIntervalSeconds", new Integer(sessionPollingIntervalSeconds));
		session.setAttribute("sessionFailedRequestsCount", new Integer(sessionFailedRequestsCount));
		session.setAttribute("sessionHeartBeatTimeoutMillis", new Integer(sessionHeartBeatTimeoutMillis));

		String val = UserNotifier.getAndRemoveAttributeFromSession(session);
		if (val != null)
			model.put(ONE_TIME_USER_NOTIFICATION, val);

		/*
		 * Add all roles and permissions to model for standard use in
		 * <security:authorize> JSP tags - CPB
		 */
		WebUtil.addClassConstantsToModel(Permission.class, model, true);
		WebUtil.addEnumToModel(PermissionType.class, model);
		WebUtil.addEnumToModel(RoleType.class, model);
		WebUtil.addEnumToModel(VAFacilityValue.class, model);
		WebUtil.addEnumToModel(FacilityValue.class, model);

		/*
		 * Add all date util constants as they are defined (without adding
		 * "DATE_UTIL_" before their names) - CPB
		 */
		WebUtil.addClassConstantsToModel(DateUtil.class, model, false);

		/* Add constants from WebUtils for global error display */
		WebUtil.addClassConstantsToModel(WebUtil.class, model);

		model.put("AJAX_CONTEXT_PATH_PREFIX", CommonWebConfig.AJAX_CONTEXT_PATH_PREFIX);

		Facility facility = SessionUtil.getFacilityContext();
		model.put("facilityContextId", facility == null ? null : facility.getId());
		model.put("facilityContextName", SessionUtil.getFacilityContextName());
		model.put("facilityContextNumMeals", SessionUtil.getFacilityContextNumMeals());
		model.put("facilityContextIsCentralOffice", SessionUtil.isFacilityContextCentralOffice());

		model.put("useMinifiedDependencies", useMinifiedDependencies);

		model.put("allStates", stateDAO.findAllSorted());

		int port = request.getServerPort();
		if (request.getScheme().equals("http") && port == 80) {
			port = -1;
		} else if (request.getScheme().equals("https") && port == 443) {
			port = -1;
		}

		String protocolHostnamePort = StringUtils.isNotBlank(protocolHostnamePortOverride)
				? protocolHostnamePortOverride
				: new URL(request.getScheme().replaceAll("[^A-Za-z0-9-\\.]", ""), request.getServerName(), port, "")
						.toString();
		model.put("protocolHostnamePort", protocolHostnamePort);
		model.put("maxGetRequestLength", maxGetRequestLength);

		addAdditionalReferenceData(request, response, handler, model);
	}

	public static void populateBasicGlobalReferenceData(Map<String, Object> model, VelocityService velocityService,
			Environment env) {
		model.put("appVersionNumber", env.getProperty("web.version"));
	}

}
