package com.capgemini.reports.common.obtaindata;

import com.capgemini.framework.teamcenter.authent.TcSession;
import com.capgemini.reports.exceptions.InvalidUserInputException;
import com.capgemini.reports.exceptions.NotFoundException;
import com.capgemini.reports.exceptions.UserInputErrorEnum;
import com.capgemini.reports.teamcenter.queries.DirectQuery;
import com.teamcenter.soa.client.model.ModelObject;
import com.teamcenter.soa.client.model.strong.ItemRevision;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;

import javax.servlet.http.HttpServletRequest;

/**
 * This class is a servlet that handles requests to perform a report on an ModelObject.
 */
@Slf4j
public abstract class AbstractObtainDataFromModelObject extends AbstractObtainDataServlet {


    private static final long serialVersionUID = 7451192554668264900L;

    private static final String OBJECT_NOT_FOUND_PREFIX = "Object not found with UID '";
    private static final String OBJECT_NOT_FOUND_SUFFIX = "'";

    @Getter
    private String uid;

    @Override
    protected JSONObject obtainData(final HttpServletRequest request, final TcSession session) throws InvalidUserInputException {

        // Obtain the URL parameters
        uid = request.getParameter("dataValues");
        log.info("Report - search uid for {}", uid);
        // findAll model object by uid
        ModelObject modelObject = getModelObject(session);

        return obtainDataFromModelObject(modelObject, session);
    }

    /**
     * The main method of this class: receives and stores information on an ModelObject.
     *
     * @param modelObject
     * @param session     a Tc session to validate the input
     * @return a {@link JSONObject} contaidning the server response that will be sent back to the browser
     * @throws InvalidUserInputException thrown when user posted invalid input parameters
     */
    protected abstract JSONObject obtainDataFromModelObject(final ModelObject modelObject, final TcSession session)
            throws InvalidUserInputException;

    /**
     * Verifies that the UID provided is not corrupt.
     *
     * @param objectUID
     * @throws InvalidUserInputException thrown if the UID is corrupt (empty, or null)
     */
    protected void validateInputUID(final String objectUID) throws InvalidUserInputException {
        if (objectUID == null) {
            throw new InvalidUserInputException("dataValues uid is null");
        }
        if (objectUID.isEmpty()) {
            throw new InvalidUserInputException(UserInputErrorEnum.OBJECT_DOES_NOT_EXIST);
        }
        log.info("Server validated parameter dataValues \"{}\"", objectUID);
    }

    /**
     * Returns the ModelObject matching the UID. Handles errors nicely.
     *
     * @param session the Tc session to make the query
     * @return the {@link ItemRevision}
     * @throws InvalidUserInputException thrown if the object couldn't be found
     */
    protected ModelObject getModelObject(final TcSession session) throws InvalidUserInputException {
        validateInputUID(uid);
        try {
            return new DirectQuery<>(session).searchByUID(uid);
        } catch (NotFoundException e) {
            throw new InvalidUserInputException(OBJECT_NOT_FOUND_PREFIX + uid + OBJECT_NOT_FOUND_SUFFIX, e);
        }
    }

}
