package com.capgemini.reports.formatting;

import com.capgemini.framework.common.FileTemplate;
import com.capgemini.framework.teamcenter.exceptions.KurtException;
import com.capgemini.reports.database.HibernateUtil;
import com.capgemini.reports.exceptions.NothingToBeShownException;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.quartz.SchedulerException;

/**
 * This abstract class allows easy creation of a js table. <br>
 * If no data exist or if an errror occurs during the table construction, an appropriate message is shown.
 */
@Slf4j
public abstract class AbstractTableFormatter extends FileTemplate {

  private static final String TAG_TABLE_DATA = "TABLE_DATA";
  private static final String TAG_ERROR_MESSAGE = "ERROR_MESSAGE";

  /**
   * Generates a html page displaying a table.<br>
   * If not elements exist in the table, shows a message that says so.<br>
   * If the DB could not be queried, shows an error message.
   *
   * @return the full html page content
   */
  public String makeJsContent() {
    SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
    Session session = sessionFactory.openSession();
    try {
      String jsDataTable = makeTable(session); // Attempt to format all the reports into a JS table
      super.setTemplateFilePath(successPageTemplateLocation());
      super.setTagValue(TAG_TABLE_DATA, jsDataTable);
      this.addOptionalTags(session);
    }
    catch (NothingToBeShownException e) {
      // This is normal behaviour: the table does not contain any matching entries. No worries
      log.trace("Normal exception: nothing to show in HMI", e);
      super.setTemplateFilePath(failedPageTemplateLocation());
      super.setTagValue(TAG_ERROR_MESSAGE, e.getErrorMessageForUser());
      this.addOptionalErrorTags();
    }
    catch (KurtException e) {
      // A Technical error occured, unable to display the screen contents
      super.setTemplateFilePath(failedPageTemplateLocation());
      super.setTagValue(TAG_ERROR_MESSAGE, e.getErrorMessageForUser());
      this.addOptionalErrorTags();
      log.debug("Unable to perform user request", e);
    }
    catch (HibernateException e) {
      super.setTemplateFilePath(failedPageTemplateLocation());
      super.setTagValue(TAG_ERROR_MESSAGE, "Impossible de communiquer avec la base de données");
      this.addOptionalErrorTags();
      log.error("A Database error occured while trying to show MyReports table", e); // This is not normal behaviour. Check query syntax, and Hibernate config
    }
    catch (SchedulerException e) {
      super.setTemplateFilePath(failedPageTemplateLocation());
      super.setTagValue(TAG_ERROR_MESSAGE, "Impossible de communiquer avec le système de planification");
      this.addOptionalErrorTags();
      log.error("An error occurred while communicationg with Quartz", e); // This is not normal behaviour. Check Quartz setup
    }
    finally {
      session.close();
    }
    return this.generateCode();
  }

  /**
   * Allows to add optional tags, if the template is a bit more complex.
   */
  protected abstract void addOptionalTags(Session session);

  /**
   * Allows to add optional tags, if the ERROR template is a bit more complex.
   */
  protected abstract void addOptionalErrorTags();

  /**
   * Main method: builds a javascript table to be inserted into the webpage.
   */
  protected abstract String makeTable(Session session) throws KurtException, SchedulerException;

  /**
   * The location of the template html page, in case the data was successfully retrieved.
   *
   * @return the file location in src/main/resources
   */
  protected abstract String successPageTemplateLocation();

  /**
   * The location of the template html page, in case the data could not be retrieved.
   *
   * @return the file location in src/main/resources
   */
  protected abstract String failedPageTemplateLocation();
}
