package gov.va.med.ars.spring.controller;

import gov.va.med.ars.imaging.VistaImaging;
import gov.va.med.ars.sec.AESEncryption;
import gov.va.med.ars.spring.dao.ClaimAttachmentsDAO;
import gov.va.med.ars.spring.dao.DbLogManagerDao;
import gov.va.med.ars.spring.dao.UserAuthorizationDao;
import gov.va.med.ars.spring.dao.UserAuthorizationDaoImpl;
import gov.va.med.ars.spring.model.ClaimAttachments;
import gov.va.med.ars.spring.model.UserAuthorization;
import gov.va.med.ars.util.FileUtils;

import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.List;

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

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

/**
 * This controller routes accesses to the application to the appropriate
 * handler methods. 
 *
 */
@Controller
public class HomeController {

	@Autowired
	private ClaimAttachmentsDAO claimAttachmentsDao;
	
	@Autowired
	private UserAuthorizationDao userAuthorizationDao;
	
	static final Logger errorLogger = Logger.getLogger("errorLogger");
	static final Logger auditLogger = Logger.getLogger("auditLogger");
	
	@Autowired
	private DbLogManagerDao dbLogManagerDao;
	
	UserAuthorization userAuth = new UserAuthorization();
	
	List<ClaimAttachments> listClaimAttachments;
	
	List<UserAuthorization> listUserAuthorization;
	
	ClaimAttachments searchCriteria = new ClaimAttachments();
	
	/**
	 * Injected from security.properties
	 */
	@Value("${login.aspCheck}")
	private String aspCheck;
	
	/**
	 * Injected from security.properties
	 */
	@Value("${login.capturedUrl}")
	private String capturedUrl;
	
	/**
	 * Injected from security.properties
	 */
	@Value("${login.forwardUrl}")
	private String forwardUrl;
	
	/**
	 * This view initiates the authentication and authorization process.
	 * Upon acceptance of the Warning by the user, the view will be
	 * posted to the authentication service provider.
	 * 
	 * @param model	Object returned to the view
	 * @param req	HttpServletRequest
	 * @param res	HttpServletResponse
	 * @return		The view to be displayed
	 */
	@RequestMapping(value={"/", "/warning"})
	public String warning(Model model, HttpServletRequest request, HttpServletResponse response) {
				
		String encryptedCapturedUrl = "";
		String encryptedForwardUrl = "";
		String encodedCapturedUrl = "";
		String encodedForwardUrl = "";
        HttpSession session = request.getSession();
		String host = request.getLocalName();
        

		auditLogger.trace("Encrypt and encode certain parameters to be posted");
    	try {    		
    		encryptedCapturedUrl = AESEncryption.encrypt(MessageFormat.format(capturedUrl, host));
			encodedCapturedUrl = URLEncoder.encode(encryptedCapturedUrl,"UTF-8");
			
			encryptedForwardUrl = AESEncryption.encrypt(MessageFormat.format(forwardUrl, host));
            encodedForwardUrl = URLEncoder.encode(MessageFormat.format(encryptedForwardUrl, host), "UTF-8");
		} catch (Exception e) {
			auditLogger.error(e);
		}

    	auditLogger.trace("Add the attributes to the model");
		model.addAttribute("aspCheck",aspCheck);
		model.addAttribute("capturedUrl", encodedCapturedUrl);
		model.addAttribute("forwardUrl", encodedForwardUrl);
		model.addAttribute("session",session.getId());
		
		return "/warning";
	}
	
	/**
	 * The view returned if the login failed.
	 * 
	 * @return		"/warning?login=failed" view
	 */
	@RequestMapping(value = "/login/failed")
	public String login() {		
		return "/warning?login=failed";
	}
	
	/**
	 * The view returned if the user attempted to access a restricted area
	 * 
	 * @return		"/error/403" view
	 */
	@RequestMapping(value = "/error/403")
	public String accessDenied() {		
		return "/error/403";
	}

	@RequestMapping(value = "/secureSearch", method = RequestMethod.GET)
	public ModelAndView secureSearch(ModelAndView model) {
		
		//String userId = System.getProperty("user.name");
		
		//get windows user id using ldap
		//TBD
		
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
	    String userId = auth.getName().split("::")[0];
		
	    /*		
	    com.sun.security.auth.module.NTSystem NTSystem = new com.sun.security.auth.module.NTSystem();
		System.out.println(NTSystem.getName());
		
		String userId = NTSystem.getName();
		*/
	    
	    System.out.println("In secureSearch, userId = " + userId);
	    
		userAuth = claimAttachmentsDao.getUserAuth(userId);
		
		if( userAuth == null)
		{
			System.out.println("User " + userId + " does not have authorization to view Attachments");
			auditLogger.info("User " + userId + " does not have authorization to view Attachments");
			model.setViewName("homepage");
		}
		else if( userAuth.getStatus().equalsIgnoreCase("D"))
		{
			System.out.println("User has been deleted & does not have authorization to view Attachments");
			auditLogger.info("User has been deleted & does not have authorization to view Attachments");
			model.setViewName("homepage");
		}
		else
		{
			System.out.println("User " + userId + " has authorization to view Attachments");
			auditLogger.info("User " + userId + " has authorization to view Attachments");
			
			model = checkSecurity(model);
			
			ClaimAttachments newClaimAttachment = new ClaimAttachments();
			
			List <String> codeDefinitions  = claimAttachmentsDao.getCodedefinitions();
			
			codeDefinitions.add(0, "ALL");
			
/*			for(String eachCode: codeDefinitions)
			{
				System.out.println("Each Code = " + eachCode);
			}*/
			
			model.addObject("ClaimAttachment", newClaimAttachment);
			model.addObject("codeList", codeDefinitions);
			
			model.setViewName("SearchClaimAttachments");
			
/*			for(int i=0;i<newClaimAttachment.getStatusValues().length;i++)
			{
				System.out.println("newClaimAttachment.statusValues = " + newClaimAttachment.getStatusValues()[i]);
				
			}*/
		}

		return model;
	}
	
	
	public ModelAndView checkSecurity(ModelAndView model)
	{
		
		if( userAuth.getDownload() == null )
		{
			model.addObject("downloadStatus", false);
		}
		else if(userAuth.getDownload().equalsIgnoreCase("Y") )
		{
			model.addObject("downloadStatus", true);
		}
		else
		{
			model.addObject("downloadStatus", false);
		}

		if( userAuth.getEdit() == null )
		{
			model.addObject("editStatus", false);
		}
		else if(userAuth.getEdit().equalsIgnoreCase("Y") )
		{
			model.addObject("editStatus", true);
		}
		else
		{
			model.addObject("editStatus", false);
		}
		
		if( userAuth.getDelete() == null )
		{
			model.addObject("deleteStatus", false);
		}
		else if(userAuth.getDelete().equalsIgnoreCase("Y") )
		{
			model.addObject("deleteStatus", true);
		}
		else
		{
			model.addObject("deleteStatus", false);
		}
		
		if( userAuth.getAdmin() == null )
		{
			model.addObject("adminStatus", false);
		}
		else if(userAuth.getAdmin().equalsIgnoreCase("Y") )
		{
			model.addObject("adminStatus", true);
		}
		else
		{
			model.addObject("adminStatus", false);
		}
		
		return model;
		
	}
	
	
/*	@RequestMapping(value = "/search", method = RequestMethod.GET)
	public ModelAndView search(ModelAndView model) {
		ClaimAttachments newClaimAttachment = new ClaimAttachments();
		model.addObject("ClaimAttachment", newClaimAttachment);
		model.setViewName("SearchClaimAttachments");
		
		for(int i=0;i<newClaimAttachment.getStatusValues().length;i++)
		{
			System.out.println("newClaimAttachment.statusValues = " + newClaimAttachment.getStatusValues()[i]);
			
		}

		return model;
		
//		return new ModelAndView("redirect:/incorrectURL.html");

	}*/
	
	@RequestMapping(value = "/searchClaimAttachments", method = RequestMethod.POST)
	public ModelAndView searchClaimAttachments(@ModelAttribute ClaimAttachments Claimattachment) {
		
		if( !Claimattachment.getReportCode().equals("ALL"))
		{
			System.out.println("Report Code = " + Claimattachment.getReportCode());
			String[] codeData = Claimattachment.getReportCode().split("-");
			Claimattachment.setReportCode(codeData[0]);
			Claimattachment.setDefinition(codeData[1]);
		}
		
		if( Claimattachment.getStatus() == null)
		{
			Claimattachment.setStatus("A");
		}
		
		//System.out.println("VMP STATUS = " + Claimattachment.getStatus());
		
		searchCriteria = Claimattachment;
		listClaimAttachments = claimAttachmentsDao.searchClaimAttachments(searchCriteria);
		
		for( ClaimAttachments attachment : listClaimAttachments)
		{
			attachment.setReportCode(attachment.getReportCode() + "-" + attachment.getDefinition());
		}
		
		ModelAndView model = new ModelAndView("SearchClaimAttachments");
		model.addObject("listClaimAttachments", listClaimAttachments);
		
		if( userAuth == null )
		{
			model.setViewName("anonymous");
			return model;
		}
		else
		{
			model = checkSecurity(model);
		}
		model.setViewName("home");
		return model;
	}
	
/*	@RequestMapping(value = "/newClaimAttachment", method = RequestMethod.GET)
	public ModelAndView newClaimAttachments(ModelAndView model) {
		ClaimAttachments newClaimAttachment = new ClaimAttachments();
		model.addObject("ClaimAttachment", newClaimAttachment);
		model.setViewName("ClaimAttachmentForm");
		return model;
	}*/
	

	
	@RequestMapping(value = "/saveClaimAttachment", method = RequestMethod.POST)
	public ModelAndView saveClaimAttachments(@ModelAttribute ClaimAttachments Claimattachment) {
		
		ModelAndView model = new ModelAndView("SearchClaimAttachments");
		if( userAuth == null )
		{
			model.setViewName("anonymous");
			return model;
		}
		else
		{
			model = checkSecurity(model);
		}
		
		if( Claimattachment.getReportCode() != null)
		{
			System.out.println("Report Code = " + Claimattachment.getReportCode());
			String[] codeData = Claimattachment.getReportCode().split("-");
			Claimattachment.setReportCode(codeData[0]);
			Claimattachment.setDefinition(codeData[1]);
		}
		
		
		claimAttachmentsDao.saveOrUpdate(Claimattachment);		
		//return new ModelAndView("redirect:/");
		listClaimAttachments = claimAttachmentsDao.searchClaimAttachments(searchCriteria);
		
		for( ClaimAttachments attachment : listClaimAttachments)
		{
			attachment.setReportCode(attachment.getReportCode() + "-" + attachment.getDefinition());
		}
		
		
		model.addObject("listClaimAttachments", listClaimAttachments);
		model.setViewName("home");
		return model;
	}

	
	@RequestMapping(value = "/deleteClaimAttachment", method = RequestMethod.GET)
	public ModelAndView deleteClaimAttachments(HttpServletRequest request) {

		ModelAndView model = new ModelAndView("SearchClaimAttachments");
		
		if( userAuth == null )
		{
			model.setViewName("anonymous");
			return model;
		}
		else
		{
			model = checkSecurity(model);
		}
		
		Integer claimAttachmentId = Integer.parseInt(request.getParameter("id"));
		claimAttachmentsDao.delete(claimAttachmentId);
		listClaimAttachments = claimAttachmentsDao.searchClaimAttachments(searchCriteria);
		model.addObject("listClaimAttachments", listClaimAttachments);
		model.setViewName("home");
		return model;
		//return new ModelAndView("home");
	}
	
	@RequestMapping(value = "/editClaimAttachment", method = RequestMethod.GET)
	public ModelAndView editClaimAttachments(HttpServletRequest request) {
		Integer claimAttachmentId = Integer.parseInt(request.getParameter("id"));
		ClaimAttachments claimAttachment = claimAttachmentsDao.get(claimAttachmentId);
		ModelAndView model = new ModelAndView("EditClaimAttachmentForm");
		
		//System.out.println("Inside editClaimAttachments");
		
		if( userAuth == null )
		{
			model.setViewName("anonymous");
			return model;
		}
		else
		{
			model = checkSecurity(model);
		}
		
		List <String> codeDefinitions  = claimAttachmentsDao.getCodedefinitions();
		
		System.out.println("claimAttachment.getReportCode() = " + claimAttachment.getReportCode());
		
		for(String eachCode: codeDefinitions)
		{
			System.out.println("Each Code = " + eachCode);
			String[] codeData = eachCode.split("-");
			
			if( claimAttachment.getReportCode().equals(codeData[0]))
			{
				claimAttachment.setReportCode(eachCode);
			}
		}
		
		codeDefinitions.add(0, claimAttachment.getReportCode());
		
		model.addObject("codeList", codeDefinitions);
		model.addObject("ClaimAttachment", claimAttachment);
		
		return model;
	}
	
	@RequestMapping(value = "/downloadClaimAttachment", method = RequestMethod.GET)
	public ModelAndView downloadClaimAttachment(HttpServletRequest request) {
		String rpcResponse = "";
		Integer claimAttachmentId = Integer.parseInt(request.getParameter("id"));
		String folderName = claimAttachmentsDao.downloadClaimAttachment(claimAttachmentId);
		ClaimAttachments claimAttachment = claimAttachmentsDao.get(claimAttachmentId);
		
		//ModelAndView model = new ModelAndView("DownloadClaimAttachmentForm");
		
		ModelAndView model = new ModelAndView("home");
		
		if( userAuth == null )
		{
			model.setViewName("anonymous");
			return model;
		}
		else
		{
			model = checkSecurity(model);
		}
		
		//ModelAndView model = new ModelAndView("home");
		if( listClaimAttachments == null)
		{
			listClaimAttachments = claimAttachmentsDao.list();
		}
		model.addObject("listClaimAttachments", listClaimAttachments);
		model.addObject("downloadedFileName", claimAttachment.getAttachmentName());
		model.addObject("folderName", folderName);
		//model.addObject("folderName", folderName);
		
		VistaImaging imaging = new VistaImaging();
		rpcResponse = imaging.importVistaImage(request, claimAttachment);
		
		rpcResponse = "Message: " + rpcResponse;
		
		model.addObject("rpcResponse", rpcResponse);
				
		return model;
	}
	
	@RequestMapping(value = "/viewClaimAttachment", method = RequestMethod.GET)
	public ResponseEntity viewClaimAttachment(HttpServletRequest request,  HttpServletResponse response) throws Exception 
	{
		FileUtils fileUtils = new FileUtils();
		Integer claimAttachmentId = Integer.parseInt(request.getParameter("id"));
		//String folderName = claimAttachmentsDao.downloadClaimAttachment(claimAttachmentId);
		
		String folderName = FileUtils.readPropertiesFile().getProperty("ars.server.save.location");
		ClaimAttachments claimAttachment = claimAttachmentsDao.get(claimAttachmentId);
		
		if( listClaimAttachments == null)
		{
			listClaimAttachments = claimAttachmentsDao.list();
		}
		try {
			//model.addObject("downloadedFileName", claimAttachment.getAttachmentName());
			//model.addObject("folderName", folderName);
			//model.addObject("folderName", folderName);
			fileUtils.openAttachment(request, response, claimAttachment, folderName);
			
			return new ResponseEntity(HttpStatus.OK);
			
		} catch (Exception e) {
			errorLogger.error("Exception thrown when opening attachment : " + e.getMessage() );
			//e.printStackTrace();
		}
	
	    return new ResponseEntity(HttpStatus.NOT_FOUND);
	}
	
	
	@RequestMapping(value = "/listUserAuthorization", method = RequestMethod.GET)
	public ModelAndView listUserAuthorization(@ModelAttribute UserAuthorization userAuthorization) {
		
		listUserAuthorization = userAuthorizationDao.list();
		
		ModelAndView model = new ModelAndView("ListUserAuthorization");
		model.addObject("listUserAuthorization", listUserAuthorization);
		
		if( userAuth == null )
		{
			model.setViewName("anonymous");
			return model;
		}
		else
		{
			model = checkSecurity(model);
		}
		model.setViewName("ListUserAuthorization");
		return model;
	}
	
	@RequestMapping(value = "/addUserAuthorization", method = RequestMethod.GET)
	public ModelAndView addUserAuthorization(@ModelAttribute UserAuthorization userAuthorization) {
		
		ModelAndView model = new ModelAndView("ListUserAuthorization");
		if( userAuth == null )
		{
			model.setViewName("anonymous");
			return model;
		}
		else
		{
			model = checkSecurity(model);
		}

		if( userAuthorizationDao == null)
		{
			System.out.println("userAuthorizationDao is NULL");
		}
		
		if( userAuthorization == null)
		{
			System.out.println("userAuthorization is NULL");
		}
		
		userAuthorizationDao.saveOrUpdate(userAuthorization);		
		listUserAuthorization = userAuthorizationDao.list();
		
				
		model.addObject("listUserAuthorization", listUserAuthorization);
		model.setViewName("ListUserAuthorization");
		return model;
	}
	
	@RequestMapping(value = "/newUserAuthorization", method = RequestMethod.GET)
	public ModelAndView newUserAuthorization(ModelAndView model) {
		UserAuthorization userAuthorization = new UserAuthorization();
		model.addObject("UserAuthorization", userAuthorization);
		model.setViewName("UserAuthorizationForm");
		return model;
	}
	
	@RequestMapping(value = "/editUserAuthorization", method = RequestMethod.GET)
	public ModelAndView editUserAuthorization(HttpServletRequest request) {
		String userId = request.getParameter("id");
		UserAuthorization userAuthorization = userAuthorizationDao.getUserAuth(userId);
		ModelAndView model = new ModelAndView("EditUserAuthorizationForm");
		
		if( userAuth == null )
		{
			model.setViewName("anonymous");
			return model;
		}
		else
		{
			model = checkSecurity(model);
		}
		
		model.addObject("UserAuthorization", userAuthorization);
		model.setViewName("EditUserAuthorizationForm");
		return model;
	}
	
	
	@RequestMapping(value = "/deleteUserAuthorization", method = RequestMethod.GET)
	public ModelAndView deleteUserAuthorization(HttpServletRequest request) {

		ModelAndView model = new ModelAndView("ListUserAuthorization");
		
		if( userAuth == null )
		{
			model.setViewName("anonymous");
			return model;
		}
		else
		{
			model = checkSecurity(model);
		}
		
		String userId = request.getParameter("id");
		userAuthorizationDao.delete(userId);
		
		listUserAuthorization = userAuthorizationDao.list();
		model.addObject("listUserAuthorization", listUserAuthorization);
		model.setViewName("ListUserAuthorization");
		return model;
	}
	
	@RequestMapping(value = "/saveUserAuthorization", method = RequestMethod.POST)
	public ModelAndView saveUserAuthorization(@ModelAttribute UserAuthorization userAuthorization) {
		
		ModelAndView model = new ModelAndView("ListUserAuthorization");
		if( userAuth == null )
		{
			model.setViewName("anonymous");
			return model;
		}
		else
		{
			model = checkSecurity(model);
		}
		
		userAuthorizationDao.saveOrUpdate(userAuthorization);		
		//return new ModelAndView("redirect:/");
		
		listUserAuthorization = userAuthorizationDao.list();
		model.addObject("listUserAuthorization", listUserAuthorization);
		model.setViewName("ListUserAuthorization");
		return model;
	}

	
	
}
