package eu.nets.sis.idrights.demoapp.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import eu.nets.sis.idrights.clientapi.exception.IDRightsClientException;
import eu.nets.sis.idrights.demoapp.service.IDRightsService;
import eu.nets.sis.idrights.demoapp.util.IDRightsUtil;
import eu.nets.sis.idrights.demoapp.util.PageUIUtil;
import no.bbs.trust.b2b.xmlapi.message.domain.B2BMessage;
import no.bbs.trust.b2b.xmlapi.message.generated.CompanyRole;
import no.bbs.trust.b2b.xmlapi.message.generated.InterpretedSigAndProcInfoTypeDef;
import no.bbs.trust.b2b.xmlapi.message.generated.SigAndProcRelations;

/**
 * 
 * Controller that handles various statuses and home page request of the application
 * by mapping the requests to the appropriate views
 *
 */
@WebServlet(name = "demoapp_controller", urlPatterns = "/idrights")
public class ApplicationController extends HttpServlet {
	
	private static Logger logger = LogManager.getLogger(ApplicationController.class);
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		PrintWriter out = response.getWriter();
		//Displays landing page with content
        PageUIUtil.streamPage(new HashMap<>(), "index.ftl", out);
	}
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String messageType = request.getParameter("message_type");
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html; charset=UTF-8");
		PrintWriter out = response.getWriter();
		

		if ("getsignaturedata".equals(messageType)) {
			PageUIUtil.streamPage(new HashMap<>(), "getsignaturedata.ftl", out);
			return;
		} 
		
		if ("verifysignaturedata".equals(messageType)) {
			PageUIUtil.streamPage(new HashMap<>(), "verifysignaturedata.ftl", out);
			return;
		}
		
		// Handle Get Signature Data request
		if (request.getParameter("getsp") != null) {
			logger.info("Get Signature Data request");
			Map<String, Object> data = getSignatureDataStatus(request);
			String page = (data.get("errorCode") != null || data.get("errorMessage") != null) ? "error.ftl" : "getsignaturedatastatus.ftl";
			PageUIUtil.streamPage(data, page, out);
			return;
		}
		
		// Handle Verify Signature Data request
		if (request.getParameter("verifysp") != null) {
			logger.info("Verify Signature Data request");
			Map<String, Object> data = verifySignatureDataStatus(request);
			String page = (data.get("errorCode") != null || data.get("errorMessage") != null) ? "error.ftl" : "verifysignaturedatastatus.ftl";
			PageUIUtil.streamPage(data, page, out);
			return;
		}
		
		logger.info("Unsupported messageType, hence moving to error page");
		Map<String, Object> data = Map.of("errorMessage", "Invalid request");
		PageUIUtil.streamPage(data, "error.ftl", out);
	}
	
	public Map<String, Object> getSignatureDataStatus(HttpServletRequest request) {
		
		String countryCode = request.getParameter("countrycode");
		String orgNo = request.getParameter("organizationNo");
		String headerText = request.getParameter("showheadertext");
		
		B2BMessage response;
		Map<String, Object> data = new HashMap<>();
		try {
			response = new IDRightsService().getSPInfoByOrgXmlRequest(countryCode, orgNo, headerText);
		} catch (IDRightsClientException e) {
			data.put("errorCode", e.getErrorCode());
			data.put("errorMessage", e.getMessage());
			return data;
		}
		if (null != response) {
			List<CompanyRole> companyRoles = response.getTrustB2BMessage().getGetSPInfoByOrgResponse().getCompanyRoles().getCompanyRole();
			List<InterpretedSigAndProcInfoTypeDef> signatureList = response.getTrustB2BMessage().getGetSPInfoByOrgResponse().getInterpretedSPInfoList().getInterpretedSPInfo();
			List<InterpretedSigAndProcInfoTypeDef> signatures = new LinkedList<>();
			for (InterpretedSigAndProcInfoTypeDef sig : signatureList) {
				if ("Signature".equals(sig.getSignatureType().value())) { // Get only Signature data from list
					if (sig.getSigAndProcRelations() == null) {
						sig.setSigAndProcRelations(new SigAndProcRelations());
					}
					signatures.add(sig);
				}
			}
			String xmlResponse = IDRightsUtil.convertB2BMsgToString(response);
			if (null != xmlResponse) {
				data.put("organizationNo", orgNo);
				data.put("roles", companyRoles);
				data.put("signaturelist", signatures);
				data.put("idrightsresponse", IDRightsUtil.convertToXMLStringFormat(xmlResponse));
				return data;
			}
		}
		data.put("errormessage", "Could not get signature data");
		return data;
	}
	
	public Map<String, Object> verifySignatureDataStatus(HttpServletRequest request) {
		String countryCode = request.getParameter("countrycode");
		String orgNo = request.getParameter("organizationNo");
		String ssnValues = request.getParameter("ssn");
		
		B2BMessage response;
		Map<String, Object> data = new HashMap<>();
		try {
			response = new IDRightsService().verifySPInfoXmlRequest(countryCode, orgNo, ssnValues);
		} catch (IDRightsClientException e) {
			data.put("errorCode", e.getErrorCode());
			data.put("errorMessage", e.getMessage());
			return data;
		}
		if (null != response) {
			String signatureType = response.getTrustB2BMessage().getVerifySignatureAndProcurationResponse().getSignatureType().value();
			String signatureConclusion = response.getTrustB2BMessage().getVerifySignatureAndProcurationResponse().getSignatureConclusion().value();
			String xmlResponse = IDRightsUtil.convertB2BMsgToString(response);
			if (null != xmlResponse) {
				data.put("organizationNo", orgNo);
				data.put("ssn", ssnValues);
				data.put("signaturetype", signatureType);
				data.put("signatureconclusion", signatureConclusion);
				data.put("idrightsresponse", IDRightsUtil.convertToXMLStringFormat(xmlResponse));
				return data;
			}
		}
		data.put("errormessage", "Could not get verify signature data");
		return data;
	}
}
