package com.capgemini.reports.execution.strategies;

import com.capgemini.framework.teamcenter.authent.TcSession;
import com.capgemini.framework.teamcenter.exceptions.KurtException;
import com.capgemini.reports.ReportLaunchTypeEnum;
import com.capgemini.reports.exceptions.InvalidUserInputException;
import com.capgemini.reports.exceptions.NoConfChangesException;
import com.capgemini.reports.execution.AbstractExecutionReport;
import com.capgemini.reports.printing.PrintParameters;

import java.io.File;
import java.io.Serializable;

/**
 * This interface represents a strategy of report's execution.<br>
 * According to the launch type, we have different strategies :<br>
 * <ul>
 * <li>A strategy for immediate reports.
 * <li>A strategy for delayed reports.
 * <li>A strategy for scheduled report.
 * </ul>
 */
public interface IExecutionStrategy extends Serializable {

  /**
   * Perform the printing step of a report : the generation of the file and the folders output.<br>
   * <ul>
   * <li>An IMMEDIATE or DELAYED report just print its report.
   * <li>A SCHEDULED report must manage its two output folders and print the report inside both of them.<br>
   * There is one folder of output an another of history.<br>
   * In the history folder, we can find all the generated scheduled report.<br>
   * In the scheduled output folder, we just find the last generated report of each scheduling.
   * </ul>
   *
   * @param printParameters {@link PrintParameters} - the parameters used in the template Jasper to do a report
   * @param report          {@link AbstractExecutionReport} - the report with his own specificities
   * @return the printed {@link File}
   * @throws KurtException
   */
  File print(final PrintParameters printParameters, final AbstractExecutionReport<?, ?> report) throws KurtException;

  /**
   * Defines what is to be done before the report starts to execute.
   *
   * @param report the report instance
   * @param <T>    the exact report type
   * @throws KurtException
   */
  <T extends AbstractExecutionReport<T, ?>> void preExecutionStep(final T report, TcSession session) throws KurtException;

  /**
   * Defines what is to be done after the report has completed its execution.
   *
   * @param <T>                   the exact report type
   * @param report                the report instance
   * @param fileNameWithExtension the file name
   * @throws KurtException
   */
  <T extends AbstractExecutionReport<T, ?>> void postExecutionStep(final T report, final String fileNameWithExtension,
                                                                   TcSession session) throws KurtException;

  /**
   * Construct the name of the file.<br>
   * For IMMEDIATE or DELAYED report, each report has its own name.<br>
   * For SCHEDULED report, the name is specific to the report code, the scheduling and the execution date.
   *
   * @param report {@link AbstractExecutionReport} - the report which his specificities (code, file name,...)
   * @return the file name
   */
  String getReportFileName(final AbstractExecutionReport<?, ?> report);

  /**
   * The type of launch (as a {@link ReportLaunchTypeEnum}).
   *
   * @return DELAYED, SCHEDULED, IMMEDIATE, AUTOMATIC
   */
  ReportLaunchTypeEnum getLaunchType();

  /**
   * Handles a functional error by the user.
   *
   * @param report the report which failed
   * @param error  the exception that was encountered (an {@link NoConfChangesException})
   */
  void handleFunctionalError(AbstractExecutionReport<?, ?> report, NoConfChangesException error);

  /**
   * Handles a functional error by the user.
   *
   * @param report the report which failed
   * @param error  the exception that was encountered (an {@link InvalidUserInputException})
   */
  void handleFunctionalError(AbstractExecutionReport<?, ?> report, InvalidUserInputException error);

  /**
   * Handles a technical error.
   *
   * @param report       the report which failed
   * @param theThrowable the exception that was encountered
   */
  void handleTechnicalError(AbstractExecutionReport<?, ?> report, Throwable theThrowable);
}
