package gov.va.vss.service.impl;

import java.time.LocalDate;
import java.time.ZoneId;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.MessageSource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;

import gov.va.shared.model.AppUser;
import gov.va.shared.model.CoreUserDetails;
import gov.va.shared.model.lookup.sds.VAFacility;
import gov.va.shared.persistence.AppUserDAO;
import gov.va.shared.persistence.lookup.PermissionDAO;
import gov.va.shared.persistence.lookup.RoleDAO;
import gov.va.shared.persistence.lookup.sds.GenderDAO;
import gov.va.shared.persistence.lookup.sds.StateDAO;
import gov.va.shared.persistence.lookup.sds.VAFacilityDAO;
import gov.va.shared.persistence.lookup.sds.VAFacilityTypeDAO;
import gov.va.shared.service.validation.ServiceValidationException;
import gov.va.shared.util.SecurityUtil;
import gov.va.vss.model.facility.Facility;
import gov.va.vss.persistence.dao.AdjustedHoursEntryDAO;
import gov.va.vss.persistence.dao.ApplicationParametersDAO;
import gov.va.vss.persistence.dao.AvailableIdentifyingCodeDAO;
import gov.va.vss.persistence.dao.AwardCodeDAO;
import gov.va.vss.persistence.dao.AwardDAO;
import gov.va.vss.persistence.dao.BinaryObjectDAO;
import gov.va.vss.persistence.dao.DonationDetailDAO;
import gov.va.vss.persistence.dao.DonationLogDAO;
import gov.va.vss.persistence.dao.DonationLogFileDAO;
import gov.va.vss.persistence.dao.DonationReferenceDAO;
import gov.va.vss.persistence.dao.DonationSummaryDAO;
import gov.va.vss.persistence.dao.DonorDAO;
import gov.va.vss.persistence.dao.ExpenditureDAO;
import gov.va.vss.persistence.dao.HolidayDAO;
import gov.va.vss.persistence.dao.LedgerAdjustmentDAO;
import gov.va.vss.persistence.dao.LetterTemplateDAO;
import gov.va.vss.persistence.dao.NationalOfficialDAO;
import gov.va.vss.persistence.dao.NotificationDAO;
import gov.va.vss.persistence.dao.OccasionalWorkEntryDAO;
import gov.va.vss.persistence.dao.ParkingStickerDAO;
import gov.va.vss.persistence.dao.PrintRequestDAO;
import gov.va.vss.persistence.dao.ServiceParametersDAO;
import gov.va.vss.persistence.dao.StationParametersDAO;
import gov.va.vss.persistence.dao.TemplateDAO;
import gov.va.vss.persistence.dao.UniformDAO;
import gov.va.vss.persistence.dao.WorkEntryDAO;
import gov.va.vss.persistence.dao.audit.AuditLogEntryDAO;
import gov.va.vss.persistence.dao.benefitingService.BenefitingServiceDAO;
import gov.va.vss.persistence.dao.benefitingService.BenefitingServiceRoleDAO;
import gov.va.vss.persistence.dao.benefitingService.BenefitingServiceRoleTemplateDAO;
import gov.va.vss.persistence.dao.benefitingService.BenefitingServiceRoleTypeDAO;
import gov.va.vss.persistence.dao.benefitingService.BenefitingServiceTemplateDAO;
import gov.va.vss.persistence.dao.donGenPostFund.DonGenPostFundDAO;
import gov.va.vss.persistence.dao.facility.FacilityDAO;
import gov.va.vss.persistence.dao.facility.KioskDAO;
import gov.va.vss.persistence.dao.facility.LocationDAO;
import gov.va.vss.persistence.dao.facility.UpdateableLocationDAO;
import gov.va.vss.persistence.dao.leie.ExcludedEntityDAO;
import gov.va.vss.persistence.dao.lookup.AdministrativeUnitDAO;
import gov.va.vss.persistence.dao.lookup.DonorTypeDAO;
import gov.va.vss.persistence.dao.lookup.FacilityTypeDAO;
import gov.va.vss.persistence.dao.lookup.LanguageDAO;
import gov.va.vss.persistence.dao.lookup.RequirementStatusDAO;
import gov.va.vss.persistence.dao.lookup.StaffTitleDAO;
import gov.va.vss.persistence.dao.lookup.VolunteerStatusDAO;
import gov.va.vss.persistence.dao.organization.OrganizationDAO;
import gov.va.vss.persistence.dao.requirement.BenefitingServiceRoleRequirementAssociationDAO;
import gov.va.vss.persistence.dao.requirement.BenefitingServiceRoleTemplateRequirementAssociationDAO;
import gov.va.vss.persistence.dao.requirement.RequirementDAO;
import gov.va.vss.persistence.dao.requirement.VolunteerRequirementDAO;
import gov.va.vss.persistence.dao.views.FacilityAndVisnDAO;
import gov.va.vss.persistence.dao.volunteer.VoluntaryServiceStaffDAO;
import gov.va.vss.persistence.dao.volunteer.VolunteerAssignmentDAO;
import gov.va.vss.persistence.dao.volunteer.VolunteerDAO;
import gov.va.vss.persistence.dao.volunteer.VolunteerOrganizationDAO;
import gov.va.vss.service.email.EmailService;
import gov.va.vss.util.DateUtil;
import gov.va.vss.util.context.SessionUtil;

@Transactional(rollbackFor = ServiceValidationException.class)
public class AbstractServiceImpl {

	@Autowired
	protected AdjustedHoursEntryDAO adjustedHoursEntryDAO;
	@Autowired
	protected AdministrativeUnitDAO administrativeUnitDAO;
	@Autowired
	protected ApplicationParametersDAO applicationParametersDAO;
	@Autowired
	protected AppUserDAO appUserDAO;
	@Autowired
	protected AuditLogEntryDAO auditLogEntryDAO;
	@Autowired
	protected AvailableIdentifyingCodeDAO availableIdentifyingCodeDAO;
	@Autowired
	protected AwardDAO awardDAO;
	@Autowired
	protected AwardCodeDAO awardCodeDAO;
	@Autowired
	protected BenefitingServiceDAO benefitingServiceDAO;
	@Autowired
	protected BenefitingServiceRoleDAO benefitingServiceRoleDAO;
	@Autowired
	protected BenefitingServiceRoleRequirementAssociationDAO benefitingServiceRoleRequirementAssociationDAO;
	@Autowired
	protected BenefitingServiceRoleTemplateDAO benefitingServiceRoleTemplateDAO;
	@Autowired
	protected BenefitingServiceRoleTemplateRequirementAssociationDAO benefitingServiceRoleTemplateRequirementAssociationDAO;
	@Autowired
	protected BenefitingServiceRoleTypeDAO benefitingServiceRoleTypeDAO;
	@Autowired
	protected BenefitingServiceTemplateDAO benefitingServiceTemplateDAO;
	@Autowired
	protected BinaryObjectDAO binaryObjectDAO;
	@Autowired
	protected DonationLogDAO donationLogDAO;
	@Autowired
	protected DonationLogFileDAO donationLogFileDAO;
	@Autowired
	protected DonationDetailDAO donationDetailDAO;
	@Autowired
	protected DonationSummaryDAO donationSummaryDAO;
	@Autowired
	protected DonationReferenceDAO donationReferenceDAO;
	@Autowired
	protected DonGenPostFundDAO donGenPostFundDAO;
	@Autowired
	protected DonorDAO donorDAO;
	@Autowired
	protected DonorTypeDAO donorTypeDAO;
	@Autowired
	protected ExcludedEntityDAO excludedEntityDAO;
	@Autowired
	protected ExpenditureDAO expenditureDAO;
	@Autowired
	protected FacilityDAO facilityDAO;
	@Autowired
	protected FacilityTypeDAO facilityTypeDAO;
	@Autowired
	protected GenderDAO genderDAO;
	@Autowired
	protected HolidayDAO holidayDAO;
	@Autowired
	protected FacilityAndVisnDAO facilityAndVisnDAO;
	@Autowired
	protected KioskDAO kioskDAO;
	@Autowired
	protected LanguageDAO languageDAO;
	@Autowired
	protected LedgerAdjustmentDAO ledgerAdjustmentDAO;
	@Autowired
	protected LetterTemplateDAO letterTemplateDAO;
	@Autowired
	protected LocationDAO locationDAO;
	@Autowired
	protected NationalOfficialDAO nationalOfficialDAO;
	@Autowired
	protected NotificationDAO notificationDAO;
	@Autowired
	protected OccasionalWorkEntryDAO occasionalWorkEntryDAO;
	@Autowired
	protected OrganizationDAO organizationDAO;
	@Autowired
	protected ParkingStickerDAO parkingStickerDAO;
	@Autowired
	protected PermissionDAO permissionDAO;
	@Autowired
	protected PrintRequestDAO printRequestDAO;
	@Autowired
	protected RequirementDAO requirementDAO;
	@Autowired
	protected RequirementStatusDAO requirementStatusDAO;
	@Autowired
	protected RoleDAO roleDAO;
	@Autowired
	protected ServiceParametersDAO serviceParametersDAO;
	@Autowired
	protected StaffTitleDAO staffTitleDAO;
	@Autowired
	protected StateDAO stateDAO;
	@Autowired
	protected StationParametersDAO stationParametersDAO;
	@Autowired
	protected TemplateDAO templateDAO;
	@Autowired
	protected UniformDAO uniformDAO;
	@Autowired
	protected UpdateableLocationDAO updateableLocationDAO;
	@Autowired
	protected VAFacilityDAO vaFacilityDAO;
	@Autowired
	protected VAFacilityTypeDAO vaFacilityTypeDAO;
	@Autowired
	protected VoluntaryServiceStaffDAO voluntaryServiceStaffDAO;
	@Autowired
	protected VolunteerDAO volunteerDAO;
	@Autowired
	protected VolunteerAssignmentDAO volunteerAssignmentDAO;
	@Autowired
	protected VolunteerOrganizationDAO volunteerOrganizationDAO;
	@Autowired
	protected VolunteerRequirementDAO volunteerRequirementDAO;
	@Autowired
	protected VolunteerStatusDAO volunteerStatusDAO;
	@Autowired
	protected WorkEntryDAO workEntryDAO;

	@Autowired
	protected SessionUtil sessionUtil;
	@Autowired
	protected DateUtil dateUtil;
	@Autowired
	protected EmailService emailService;
	@Autowired
	protected MessageSource messageSource;
	@Autowired
	@Qualifier("transactionManager")
	protected PlatformTransactionManager tm;

	protected VAFacility getSiteContext() {
		return gov.va.shared.util.context.SessionUtil.getSiteContext();
	}

	protected VAFacility getRequiredSiteContext() {
		VAFacility f = getSiteContext();
		if (f == null)
			throw new IllegalStateException("A site context was required but not found.");
		return f;
	}

	protected Facility getFacilityContext() {
		VAFacility siteContext = getSiteContext();
		if (siteContext == null)
			return null;

		Facility f = facilityDAO.findByVAFacility(siteContext.getId());
		return f;
	}

	protected Facility getRequiredFacilityContext() {
		Facility f = getFacilityContext();
		if (f == null)
			throw new IllegalStateException("A facility context was required but not found.");
		return f;
	}

	protected ZoneId getFacilityTimeZone() {
		Facility fc = getFacilityContext();
		return fc == null ? ZoneId.systemDefault() : fc.getTimeZone();
	}

	protected LocalDate getTodayAtFacility() {
		return LocalDate.now(getFacilityTimeZone());
	}

	/**
	 * Returns the current AppUser, or null if there is no current user or the
	 * current user is not an AppUser (e.g. is a background daemon user). See
	 * SecurityUtil.getCurrentUserAsOrNull for details. CPB
	 */
	protected CoreUserDetails getCurrentUser() {
		return SecurityUtil.getCurrentUserAsOrNull(CoreUserDetails.class);
	}

	protected <T extends CoreUserDetails> T getCurrentUserAsOrNull(Class<T> c) {
		return SecurityUtil.getCurrentUserAsOrNull(c);
	}

	protected AppUser getBatchJobUser() {
		AppUser appUser = new AppUser();
		appUser.setEnabled(true);
		appUser.setLastName("System Batch Job");
		appUser.setTimeZone(ZoneId.systemDefault());
		return appUser;
	}
}
