package com.capgemini.reports.database;

import com.capgemini.framework.common.SettingsHelper;
import com.capgemini.reports.database.javabean.enumeration.ReportCriteriaEnum;
import com.capgemini.reports.database.manager.*;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

/**
 * Database initialization using Hibernate.
 **/
@Slf4j
public class DbInit {

  private final MngCriteria criteriaManager;
  private final MngCriteriaVal criteriaValManager;
  private final MngReportType reportTypeManager;
  private final MngReportOwner reportOwnerManager;
  private final MngReport reportManager;
  private final MngUser userManager;

  private static final String[] reports =
    new String[]{"R01", "R03", "R05", "R06", "R07", "R10", "R11", "R13", "R15", "R16", "R17", "R19", "R20", "R21", "R22", "R23", "R24", "R26", "R27", "R28"};

  /**
   * Main entry point for initializer.
   *
   * @param args JAVA command arguments (should be empty)
   */
  public static void main(final String[] args) {
    SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
    Session session = sessionFactory.openSession();
    Transaction transaction = session.beginTransaction();
    try {
      DbInit theInitializer = new DbInit();
      log.info("Create all objects");
      theInitializer.createAllObjects(session);

      log.info("Commit transaction");
      transaction.commit();

      log.info("Display record count");
      theInitializer.displayRecordCount(session);
    }
    catch (Exception e) {
      log.error("Unexpected error occured during database initialization", e);
      log.warn("Rollback transaction");
      transaction.rollback();
    }
    finally {
      log.info("End of initialization");
      session.close();
    }
  }

  private DbInit() {
    criteriaManager = new MngCriteria();
    criteriaValManager = new MngCriteriaVal();
    reportManager = new MngReport();
    reportTypeManager = new MngReportType();
    userManager = new MngUser();
    reportOwnerManager = new MngReportOwner();
  }

  /**
   * Sample objects creation.
   */
  private void createAllObjects(Session session) {
    log.info("Create users");
    userManager.insert(session, "infodba", "System", "Administrator", SettingsHelper.getDefaultExpeditorMailPassword());

    log.info("Create criteria");
    for (ReportCriteriaEnum currentEnum : ReportCriteriaEnum.values()) {
      String currentType = "string";
      String currentStrValue = currentEnum.toString();
      if (currentStrValue.startsWith("Unit")) {
        currentType = "integer";
      }
      else if (currentStrValue.startsWith("Date")) {
        currentType = "date";
      }
      criteriaManager.insert(session, currentEnum, currentType);
    }

    log.info("Create report types");
    String defaultRevRule = SettingsHelper.getDefaultRevisionRule();
    for (String report : reports) {
      reportTypeManager.insert(session, report, SettingsHelper.getString("title.REPORT_" + report),
        Long.valueOf(SettingsHelper.getString("priority.REPORT_" + report)),
        SettingsHelper.getPropertyWithDefaultValue("common.bom.revisionRule.REPORT_" + report, defaultRevRule));
    }
  }

  /**
   * Display a summary of loaded objects.
   *
   * @param session*/
  private void displayRecordCount(Session session) {
    log.info("Loaded user(s) count: " + reportManager.getList(session).size());
    log.info("Loaded criteria(s) count: " + criteriaManager.getList(session).size());
    log.info("Loaded criteria value(s) count: " + criteriaValManager.getList(session).size());
    log.info("Loaded report(s) count: " + userManager.getList(session).size());
    log.info("Loaded reportOwner(s) count: " + reportOwnerManager.getList(session).size());
  }
}
