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.strong.ItemRevision;
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 ItemRevision.
 */
@Slf4j
public abstract class AbstractObtainDataFromItemRevision extends AbstractObtainDataServlet {
    private static final long serialVersionUID = 7666172651622505390L;

    @Override
    protected JSONObject obtainData(final HttpServletRequest request, final TcSession session) throws InvalidUserInputException {
        // Obtain the URL parameters
        String objectUID = request.getParameter("dataValues");

        ItemRevision itemRev = getItemRevisionByIUD(objectUID, session);

        String itemID = getItemID(itemRev);
        String itemRevisionID = getItemRevisionID(itemRev);
        String itemType = itemRev.getTypeObject().getName();
        return obtainDataFromItemRevision(itemID, itemRevisionID, itemType, session);
    }

    /**
     * Obtains the ItemID of the {@link ItemRevision}. Handles errors nicely.
     *
     * @param itemRev the Revision ID of the object
     * @return the item Id
     * @throws InvalidUserInputException thrown in case of internal errors: some properties might not be loaded
     */
    private String getItemID(final ItemRevision itemRev) throws InvalidUserInputException {
        return itemRev.get_item_id();
    }

    /**
     * The main method of this class: receives and stores information on an ItemRevision.
     */
    protected abstract JSONObject obtainDataFromItemRevision(final String itemID, final String itemRevisionID, final String itemType,
                                                             final TcSession session) throws InvalidUserInputException;


    /**
     * Obtains the revision ID of the {@link ItemRevision}. Handles errors nicely.
     *
     * @param itemRev the ItemRevision
     * @return the itemRevision Id
     * @throws InvalidUserInputException thrown in case of internal errors: some properties might not be loaded
     */
    private String getItemRevisionID(final ItemRevision itemRev) throws InvalidUserInputException {
        return itemRev.get_item_revision_id();
    }

    /**
     * Verifies that the UID provided is not corrupt.
     *
     * @param objectUID the object UID
     * @throws InvalidUserInputException thrown if the UID is corrupt (empty, or null)
     */
    private 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 ItemRevision matching the UID provided. Handles errors nicely.
     *
     * @param uid     the item UID
     * @param session the Tc session to make the query
     * @return the {@link ItemRevision}
     * @throws InvalidUserInputException thrown if the object couldn't be found
     */
    private ItemRevision getItemRevisionByIUD(final String uid, final TcSession session) throws InvalidUserInputException {
        validateInputUID(uid);
        try {
            return new DirectQuery<ItemRevision>(session).searchByUID(uid);
        } catch (NotFoundException e) {
            throw new InvalidUserInputException("Object not found with UID '" + uid + "'", e);
        }
    }
}
