package com.capgemini.reports.common.scheduling.utilities;

import com.capgemini.framework.teamcenter.exceptions.KurtException;
import com.capgemini.reports.exceptions.InsufficientParametersException;
import com.capgemini.reports.exceptions.InvalidInputException;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Class used to perform operations on Schedulings.<br>
 * Example operations:
 * <ul>
 * <li><b>get_sub_period</b> used to obtain the existing parameters of a scheduling when updating it from HMI</li>
 * <li><b>save</b> used to set activation status of a particular report</li>
 * <li><b>is_authorised_report</b> used to obtain activation status of a particular report</li>
 * </ul>
 */
@Slf4j
public abstract class AbstractActionManager extends HttpServlet {

    private static final long serialVersionUID = 3744965867042379548L;

    private static final String CONTENT_TYPE_JSON = "application/json";

    /** This key can be found in the URL. i.e. 'kurt-web/activateDeactivate?reportCode=R01&reportAuthorized=true' etc. */
    protected static final String URL_KEY_REPORT_CODE = "reportCode";

    /**
     * TOKEN to obtain request TcReleaseStatus from the JSON response.
     */
    public static final String TOKEN_STATUS = "status";
    /** TOKEN to obtain error explanation from the JSON response when STATUS is FAILED. */
    public static final String TOKEN_ERROR = "error";
    /** TOKEN to obtain success message from the JSON response. */
    public static final String TOKEN_SUCCESS_MSG = "success";

    /** STATUS value for the JSON response when posting is successful. */
    public static final String STATUS_SUCCESS = TOKEN_SUCCESS_MSG;
    /** STATUS value for the JSON response when posting has failed. */
    public static final String STATUS_FAILED = "failed";
    /** STATUS value for the JSON response when user should be prompted before actually launching the report. */
    public static final String STATUS_PROMPT = "prompt";

    @Override
    protected void doGet(final HttpServletRequest aRequest, final HttpServletResponse aResponse) throws ServletException, IOException {
        doPost(aRequest, aResponse);
    }

    @Override
    protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
        try {
            String json = perform(request, response).toString();
            response.getWriter().write(json);
        } catch (InsufficientParametersException | InvalidInputException e) {
            log.error(e.getMessage(), e);
            response.setContentType(CONTENT_TYPE_JSON);
            response.getWriter().write(errorMessage(e).toString());
        }
    }

    protected abstract JSONObject perform(final HttpServletRequest request, final HttpServletResponse response)
            throws InsufficientParametersException, InvalidInputException;

    /**
     * Helper function to return standardized success messages to the client.
     * 
     * @param msg the message
     * @return the {@link JSONObject}
     */
    protected static JSONObject successMessage(final String msg) {
        return new JSONObject().put(TOKEN_STATUS, STATUS_SUCCESS).put(TOKEN_SUCCESS_MSG, msg);
    }

    /**
     * Helper function for producing standardized JSON error messages to be sent to server in case a fault is found.
     * 
     * @param msg the message
     * @return the {@link JSONObject}
     */
    public static JSONObject errorMessage(final String msg) {
        return new JSONObject().put(TOKEN_STATUS, STATUS_FAILED).put(TOKEN_ERROR, msg);
    }

    /**
     * Helper function for producing standardized JSON error messages to be sent to server in case a fault is found.
     * 
     * @param exception the generic {@link KurtException} that caused the failure
     * @return the {@link JSONObject} containing the status and a generic error message
     */
    protected static JSONObject errorMessage(final KurtException exception) {
        return new JSONObject().put(TOKEN_STATUS, STATUS_FAILED).put(TOKEN_ERROR, exception.getMessage());
    }

    /**
     * Try to findAll an argument value in the URL and return an error message in JSP when it failed.
     * 
     * @param aRequest the {@link HttpServletRequest}
     * @param anArgName the argument you're looking for
     * @return the argument's value
     * @throws InsufficientParametersException if the URL argument requested couldn't be found in the {@link HttpServletRequest}
     */
    protected static String getMandatoryArg(final HttpServletRequest aRequest, final String anArgName) throws InsufficientParametersException {
        String theArgValue = aRequest.getParameter(anArgName);
        log.debug("Arg name {}\targ Value {}", anArgName, theArgValue);
        if (theArgValue == null) {
            String theErrorMessage = "Missing required argument in URL: " + anArgName;
            throw new InsufficientParametersException(theErrorMessage);
        }
        return theArgValue;
    }

}
