package com.jens.rhasspy.shoppinglist;


import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DatabaseHandler implements Runnable
{
	private static DatabaseHandler instance = null;
	static final String databaseConnectionEncoding = "utf8";
	
	Connection conn = null;
	
	private DatabaseHandler()
	{
	}
	
	public static DatabaseHandler getInstance()
	{
		if(instance == null)
			instance = new DatabaseHandler();
		
		return instance;
	}
	
	public Connection getConnection()
	{
//		if(isConnectedToDatabase())
//		{
//			// It has occured that the connection was there, but dead due to timeout or whatever
//			try
//			{
//				conn.getSchema();
//			}
//			catch (SQLException e)
////			if(conn.isValid(5000))
//			{
//				Miscellaneous.logEvent("DB connection probably dropped. Reestablishing...");
//				conn = null;
//				establishConnection();
//			}
//		}
		
		if(!isConnectedToDatabase())
		    establishConnection(true);
		
		return this.conn;
	}
	
	/** force means that connection is definitely reestablished, even if there seems to be an existing one **/
	private synchronized void establishConnection(boolean force)
	{
		if(conn == null | force)
		{			
			for(String dbServer : Settings.databaseServerNames)
			{
				Miscellaneous.logEvent("Trying to connect to database " + Settings.databaseName + "@" + dbServer + " as " + Settings.databaseUsername + "...", 3);
				
//				String url = "jdbc:mysql://" + dbServer + ":" + Settings.databasePort + "/";
//		        String driver = "com.mysql.jdbc.Driver";
				String url = "jdbc:mariadb://" + dbServer + ":" + Settings.databasePort + "/";
		        String driver = "org.mariadb.jdbc.Driver";
		        try
		        {
			        Class.forName(driver).newInstance();
			        conn = DriverManager.getConnection(url + Settings.databaseName + "?characterEncoding=" + databaseConnectionEncoding, Settings.databaseUsername, Settings.databasePassword);
					Miscellaneous.logEvent("Connected to database.", 3);
					
					break;
		        }
		        catch (ClassNotFoundException e)
		        {
		        	Miscellaneous.logEvent(Settings.languageBlock.get("dbDriverNotFound"), 1);
		        }
		        catch (Exception e)
		        {
		        	Miscellaneous.logEvent(Settings.languageBlock.get("dbCouldNotConnect"), 1);
		        	Miscellaneous.logEvent(Diverse.getStackTraceAsString(e), 2);
		        	this.conn = null;
		        }
			}
		}
	}
	
	public void disconnect()
	{
		// TODO: Timeout after which the DB connection is terminated automatically.
		
		if(conn != null)
		{
			Miscellaneous.logEvent("Disconnecting from database.", 3);
			try
			{
				this.conn.close();
			}
			catch (SQLException e)
			{
				Miscellaneous.logEvent(Diverse.getStackTraceAsString(e), 1);
			}
		}
		else
			Miscellaneous.logEvent("Not disconnecting from database because not connected.", 4);
		
		conn=null;
	}

	@Override
	protected void finalize() throws Throwable
	{
		disconnect();
	}

	@Override
	public void run()
	{
		getConnection();
	}

	public boolean isConnectedToDatabase()
	{
		try
		{
			if(conn != null && conn.isValid(5000))
				return true;
		}
		catch (SQLException e)
		{
			Miscellaneous.logEvent(Diverse.getStackTraceAsString(e), 1);
		}
		
		return false;
	}
}