/*
 * The Kuali Financial System, a comprehensive financial management system for higher education.
 *
 * Copyright 2005-2016 The Kuali Foundation
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.kuali.kfs.kns.web.struts.form;

import org.apache.log4j.Logger;
import org.apache.struts.action.ActionMapping;
import org.kuali.kfs.krad.exception.ExceptionIncident;
import org.kuali.kfs.krad.util.KRADConstants;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * This class is the action form for all Question Prompts.
 */
public class KualiExceptionIncidentForm extends KualiForm {
    private static final long serialVersionUID = 831951332440283401L;
    private static Logger LOG = Logger.getLogger(KualiExceptionIncidentForm.class);

    /**
     * The form properties that should be populated in order for the toMap() method to function properly.
     */
    private static final Set<String> PROPS_NEEDED_FOR_MAP = new HashSet<String>();

    static {
        PROPS_NEEDED_FOR_MAP.add(ExceptionIncident.DOCUMENT_ID);
        PROPS_NEEDED_FOR_MAP.add(ExceptionIncident.USER_EMAIL);
        PROPS_NEEDED_FOR_MAP.add(ExceptionIncident.USER_NAME);
        PROPS_NEEDED_FOR_MAP.add(ExceptionIncident.UUID);
        PROPS_NEEDED_FOR_MAP.add(ExceptionIncident.COMPONENT_NAME);
        PROPS_NEEDED_FOR_MAP.add(ExceptionIncident.DESCRIPTION);
        PROPS_NEEDED_FOR_MAP.add(ExceptionIncident.EXCEPTION_REPORT_SUBJECT);
        PROPS_NEEDED_FOR_MAP.add(ExceptionIncident.EXCEPTION_MESSAGE);
        PROPS_NEEDED_FOR_MAP.add(ExceptionIncident.DISPLAY_MESSAGE);
        PROPS_NEEDED_FOR_MAP.add(ExceptionIncident.STACK_TRACE);
    }

    /**
     * Flag to determine whether it's cancel action
     */
    private boolean cancel = false;
    /**
     * Object containing exception information
     */
//    private KualiExceptionIncident exceptionIncident;
    /**
     * The error subject created from current settings and thrown exception
     */
    private String exceptionReportSubject;
    /**
     * The error message
     */
    private String exceptionMessage;
    /**
     * The error message to be displayed
     */
    private String displayMessage;
    /**
     * Additional message from user
     */
    private String description;
    /**
     * Document id. it's blank if not a document process
     */
    private String documentId = "";
    /**
     * Session user email address
     */
    private String userEmail = "";
    /**
     * Session user name
     */
    private String principalName = "";
    /**
     * Session user name
     */
    private String userName = "";
    /**
     * Detail message not for displaying
     */
    private String stackTrace;
    /**
     * Form that threw the exception
     */
    private String componentName;

    /**
     * @see org.kuali.rice.krad.web.struts.pojo.PojoForm#populate(javax.servlet.http.HttpServletRequest)
     */
    public void populate(HttpServletRequest request) {

        super.populate(request);

        // KULRICE-4402: ie explorer needs this.
        if (notNull(request.getParameter(KRADConstants.CANCEL_METHOD + ".x")) && notNull(request.getParameter(
            KRADConstants.CANCEL_METHOD + ".y"))) {
            this.setCancel(true);
        }
    }

    private boolean notNull(String s) {
        if (s != null && !"".equals(s)) {
            return true;
        } else
            return false;
    }

    /*
     * Reset method - reset attributes of form retrieved from session otherwise
     * we will always call docHandler action
     * @param mapping
     * @param request
     */
    public void reset(ActionMapping mapping, HttpServletRequest request) {

        this.setMethodToCall(null);
        this.setRefreshCaller(null);
        this.setAnchor(null);
        this.setCurrentTabIndex(0);

        this.cancel = false;
        this.documentId = null;
        this.componentName = null;
        this.description = null;
        this.displayMessage = null;
        this.exceptionMessage = null;
        this.stackTrace = null;
        this.userEmail = null;
        this.userName = null;
        this.principalName = null;

    }

    /**
     * This method return list of required information contained by the jsp in both
     * display and hidden properties.
     *
     * @return <p>Example:
     * <code>
     * documentId, 2942084
     * userEmail, someone@somewhere
     * userName, some name
     * componentFormName, Form that threw exception name
     * exceptionMessage, Error message from exception
     * displayMessage, Either exception error message or generic exception error message
     * stackTrace, Exception stack trace here
     * </code>
     */
    public Map<String, String> toMap() {
        if (LOG.isTraceEnabled()) {
            String message = String.format("ENTRY");
            LOG.trace(message);
        }

        Map<String, String> map = new HashMap<String, String>();
        map.put(ExceptionIncident.DOCUMENT_ID, this.documentId);
        map.put(ExceptionIncident.USER_EMAIL, this.userEmail);
        map.put(ExceptionIncident.USER_NAME, this.userName);
        map.put(ExceptionIncident.UUID, this.principalName);
        map.put(ExceptionIncident.COMPONENT_NAME, this.componentName);
        map.put(ExceptionIncident.DESCRIPTION, this.description);
        map.put(ExceptionIncident.EXCEPTION_REPORT_SUBJECT, this.exceptionReportSubject);
        map.put(ExceptionIncident.EXCEPTION_MESSAGE, this.exceptionMessage);
        map.put(ExceptionIncident.DISPLAY_MESSAGE, this.displayMessage);
        map.put(ExceptionIncident.STACK_TRACE, this.stackTrace);

        if (LOG.isTraceEnabled()) {
            String message = String.format("ENTRY %s", map.toString());
            LOG.trace(message);
        }

        return map;
    }

    /**
     * @return the cancel
     */
    public final boolean isCancel() {
        return this.cancel;
    }

    /**
     * @param cancel the cancel to set
     */
    public final void setCancel(boolean cancel) {
        this.cancel = cancel;
    }

    /**
     * @return the exceptionIncident
     */
//    public final KualiExceptionIncident getExceptionIncident() {
//        return this.exceptionIncident;
//    }

    /**
     * @return the description
     */
    public final String getDescription() {
        return this.description;
    }

    /**
     * @param description the description to set
     */
    public final void setDescription(String description) {
        this.description = description;
    }

    /**
     * @return the exceptionMessage
     */
    public final String getExceptionMessage() {
        return this.exceptionMessage;
    }

    /**
     * @param exceptionMessage the exceptionMessage to set
     */
    public final void setExceptionMessage(String exceptionMessage) {
        this.exceptionMessage = exceptionMessage;
    }

    /**
     * @return the displayMessage
     */
    public final String getDisplayMessage() {
        return this.displayMessage;
    }

    /**
     * @param displayMessage the displayMessage to set
     */
    public final void setDisplayMessage(String displayMessage) {
        this.displayMessage = displayMessage;
    }

    /**
     * @return the documentId
     */
    public final String getDocumentId() {
        return this.documentId;
    }

    /**
     * @param documentId the documentId to set
     */
    public final void setDocumentId(String documentId) {
        this.documentId = documentId;
    }

    /**
     * @return the userEmail
     */
    public final String getUserEmail() {
        return this.userEmail;
    }

    /**
     * @param userEmail the userEmail to set
     */
    public final void setUserEmail(String userEmail) {
        this.userEmail = userEmail;
    }

    /**
     * @return the principalName
     */
    public String getPrincipalName() {
        return this.principalName;
    }

    /**
     * @param principalName the principalName to set
     */
    public void setPrincipalName(String principalName) {
        this.principalName = principalName;
    }

    /**
     * @return the userName
     */
    public final String getUserName() {
        return this.userName;
    }

    /**
     * @param userName the userName to set
     */
    public final void setUserName(String userName) {
        this.userName = userName;
    }

    /**
     * @param stackTrace the stackTrace to set
     */
    public final void setStackTrace(String stackTrace) {
        this.stackTrace = stackTrace;
    }

    /**
     * @return the stackTrace
     */
    public final String getStackTrace() {
        return this.stackTrace;
    }

    /**
     * @return the exceptionReportSubject
     */
    public final String getExceptionReportSubject() {
        return this.exceptionReportSubject;
    }

    /**
     * @param exceptionReportSubject the exceptionReportSubject to set
     */
    public final void setExceptionReportSubject(String exceptionReportSubject) {
        this.exceptionReportSubject = exceptionReportSubject;
    }

    /**
     * @return the componentName
     */
    public final String getComponentName() {
        return this.componentName;
    }

    /**
     * @param componentName the componentName to set
     */
    public final void setComponentName(String componentName) {
        this.componentName = componentName;
    }

    /**
     * This overridden method ...
     *
     * @see org.kuali.rice.krad.web.struts.form.KualiForm#shouldMethodToCallParameterBeUsed(java.lang.String, java.lang.String, javax.servlet.http.HttpServletRequest)
     */
    @Override
    public boolean shouldMethodToCallParameterBeUsed(
        String methodToCallParameterName,
        String methodToCallParameterValue, HttpServletRequest request) {
        // we will allow all method to calls since the KualiExceptionHandlerAction will ignore the methodToCall
        return true;
    }

    /**
     * @see org.kuali.rice.krad.web.struts.form.KualiForm#shouldPropertyBePopulatedInForm(java.lang.String, javax.servlet.http.HttpServletRequest)
     */
    @Override
    public boolean shouldPropertyBePopulatedInForm(
        String requestParameterName, HttpServletRequest request) {
        if (PROPS_NEEDED_FOR_MAP.contains(requestParameterName)) {
            return true;
        } else if (KRADConstants.CANCEL_METHOD.equals(requestParameterName)) {
            return true;
        }
        return super.shouldPropertyBePopulatedInForm(requestParameterName, request);
    }
}

