package com.capgemini.reports.execution.actions;

import com.capgemini.framework.teamcenter.authent.TcSession;
import com.capgemini.framework.teamcenter.exceptions.KurtException;
import com.capgemini.reports.database.javabean.DbReport;
import com.capgemini.reports.exceptions.InvalidUserInputException;
import com.capgemini.reports.execution.AbstractExecutionReport;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;

/**
 * This abstract class makes it easy do define a report-specific action, with strong typing.<br>
 * Intercepts the default (weakly-typed)<br>
 * {@link IPostExecutionStep#performPostAction(TcSession, AbstractExecutionReport, DbReport, String) performPostAction}<br>
 * And forwards it to this class's (strongly-typed)<br>
 * {@link AbstractPostExecutionStep#performPostActionOnReport(TcSession, AbstractExecutionReport, DbReport, String)}
 *
 * @param <T> the exact report type
 * @param <R> Return type. Use {@link Void} for nothing.
 */
@AllArgsConstructor
@EqualsAndHashCode
public abstract class AbstractPostExecutionStep<T extends AbstractExecutionReport<T, ?>, R> implements IPostExecutionStep {
    private static final long serialVersionUID = -1817048657143927445L;

    @Getter(value = AccessLevel.PROTECTED)
    private final Class<T> reportClass;

    @Override
    public <K extends AbstractExecutionReport<K, ?>> void performPostAction(TcSession session, K reportRaw, DbReport theExecutingReport,
                                                                            String fileNameWithExtension) throws KurtException {
        try {
            T report = reportClass.cast(reportRaw);
            performPostActionOnReport(session, report, theExecutingReport, fileNameWithExtension);
        } catch (ClassCastException e) {
            throw new KurtException(
                    "Unable to perform Specialized action because input report is not of the right type, UID=" + reportRaw.getReportTechnicalUid(),
                    e);
        }
    }

    /**
     * Performs a specific action on a particular report type to perform after the report execution.
     *
     * @param session               a Teamcenter session (active)
     * @param reportRaw             the report which has just finished printing
     * @param dbReport              the Db object
     * @param fileNameWithExtension the filename of the report (includes extension)
     * @throws KurtException anything that happens must be a {@link KurtException} so it can be caught and dealt with appropriately. <br>
     *                       Particularly, if the error is a functional error, do throw an {@link InvalidUserInputException}
     */
    protected abstract R performPostActionOnReport(TcSession session, T reportRaw, DbReport dbReport,
                                                   String fileNameWithExtension) throws KurtException;

}
