package br.com.elotech.commom;

import br.com.elotech.model.social.*;
import br.com.elotech.params.ConnParams;
import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.service.ServiceRegistry;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.util.Properties;

public class ConnectionUtil {
  private static final Logger logger = Logger.getLogger(ConnectionUtil.class);
  private static ServiceRegistry serviceRegistry;
  private static SessionFactory sessionFactory;
  private static Configuration config;
  private static ConnParams connParams;
  private static Document doc = null;
  private static String HOMO_PATH = "WebESO\\html\\WebSocialUtil\\";

  static {
    try {
      config = getConfig();
      serviceRegistry = new StandardServiceRegistryBuilder().applySettings(config.getProperties()).build();
      config.setSessionFactoryObserver(new SessionFactoryObserver() {
        public void sessionFactoryCreated(SessionFactory sessionFactory) {

        }

        public void sessionFactoryClosed(SessionFactory sessionFactory) {
          StandardServiceRegistryBuilder.destroy(serviceRegistry);
        }
      });
      sessionFactory = config.buildSessionFactory(serviceRegistry);
    } catch (Throwable ex) {
      System.err.println("Initial SessionFactory creation failed." + ex);
      throw new ExceptionInInitializerError(ex);
    }
  }

  public static Connection getConnection() throws Exception {
    return serviceRegistry.getService(ConnectionProvider.class).getConnection();
  }

  public static Session getSession() throws Exception {
    return sessionFactory.openSession();
  }
  private static Configuration getConfig() throws ParserConfigurationException, SAXException, IOException {
    readFileConn();
    Properties prop = new Properties();
    String driver = (connParams.getDriver().equals("PDO_PGSQL") ? "org.postgresql.Driver" : "oracle.jdbc.driver.OracleDriver");
    String dialect = (connParams.getDriver().equals("PDO_PGSQL") ? "org.hibernate.dialect.PostgreSQLDialect" : "org.hibernate.dialect.OracleDialect");
    String config = connParams.getHost().concat(":").concat(connParams.getPorta()).concat("/").concat(connParams.getBanco());
    String url = (connParams.getDriver().equals("PDO_PGSQL") ? "jdbc:postgresql://" : "jdbc:oracle:thin://");
    prop.setProperty("hibernate.connection.driver_class", driver);
    prop.setProperty("hibernate.connection.url", url.concat(config));
    prop.setProperty("hibernate.connection.username", connParams.getUsername());
    prop.setProperty("hibernate.connection.password", connParams.getPassword());
    prop.setProperty("hibernate.dialect", dialect);
    prop.setProperty("hibernate.hbm2ddl.auto", "validate");
    prop.setProperty("hibernate.cache.provider_class", "org.hibernate.cache.NoCacheProvider");
    prop.setProperty("hibernate.current_session_context_class", "thread");

    prop.setProperty("hibernate.show_sql", "false");
    prop.setProperty("hibernate.format_sql", "true");
    prop.setProperty("hibernate.use_sql_comments", "true");

    Configuration cfg = new Configuration();
    /* Mapeia as classes do hibernate */
    cfg
      .addAnnotatedClass(AsProntuarioSuas.class)
      .addAnnotatedClass(AsProntuarioSuasUsuario.class)
      .addAnnotatedClass(AsProntuarioSuasUnidade.class)
      .addAnnotatedClass(AsTipoCertidao.class)
      .addAnnotatedClass(Usuarios.class)
      .addAnnotatedClass(Usuario.class)
      .addAnnotatedClass(Unidade.class)
      .addAnnotatedClass(CadUniArquivo.class);
    /* -------------- */
    cfg.setProperties(prop);
    logger.info("Conectado a base: ".concat(connParams.getBanco().toUpperCase()));
    return cfg;
  }

  private static void readFileConn() throws IOException, SAXException, ParserConfigurationException {
    String jarpath = System.getProperty("user.dir");
    String path = jarpath.contains(HOMO_PATH) ? "/../../WebSocialComum/library/conf/" : "/../library/conf/";
    doc = readXmlFile(new File(jarpath.concat(path).concat("dbConfig.xml")).getAbsoluteFile());
    setConnParams();
  }

  private static void setConnParams() {
    connParams = new ConnParams();
    connParams.setDriver(Util.convertBase64(doc.getElementsByTagName("adapter").item(0).getTextContent()));
    connParams.setBanco(Util.convertBase64(doc.getElementsByTagName("dbname").item(0).getTextContent()));
    connParams.setHost(Util.convertBase64(doc.getElementsByTagName("host").item(0).getTextContent()));
    connParams.setPorta(Util.convertBase64(doc.getElementsByTagName("porta").item(0).getTextContent()));
    connParams.setUsername(Util.convertBase64(doc.getElementsByTagName("user").item(0).getTextContent()));
    connParams.setPassword(Util.convertBase64(doc.getElementsByTagName("password").item(0).getTextContent()));
//    connParams.setDriver("PDO_PGSQL");
//    connParams.setBanco("SANTAFE");
//    connParams.setHost("localhost");
//    connParams.setPorta("5432");
//    connParams.setUsername("postgres");
//    connParams.setPassword("postgres");
  }

  private static Document readXmlFile(File file) throws ParserConfigurationException, IOException, SAXException {
    DocumentBuilder dBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    Document doc = dBuilder.parse(file);
    doc.getDocumentElement().normalize();
    return doc;
  }
}
