package de.hottis.measurementCollector;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;
import java.util.Timer;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class DatabaseEngine extends Thread implements ITriggerable {
	static final String DATABASE_ENGINE_PERIOD_PROP = "db.period";
	static final String DATABASE_URL_PROP = "db.url";
	
	final protected Logger logger = LogManager.getRootLogger();

	private Properties config;
	private MyQueue<ADataObject> queue;
	private boolean stop;
	private boolean triggerFlag;
	private Timer timer;
	private int period;
	private String dbUrl;

	public DatabaseEngine(Properties config, MyQueue<ADataObject> queue) {
		super("MeasurementCollector.DatabaseEngine");
		this.config = config;
		this.queue = queue;
		this.stop = false;
		this.triggerFlag = false;
		this.period = Integer.parseInt(this.config.getProperty(DATABASE_ENGINE_PERIOD_PROP));
		this.dbUrl = this.config.getProperty(DATABASE_URL_PROP);
	}

	public void requestShutdown() {
		logger.info("Shutdown of database engine requested");
		this.stop = true;
		try {
			this.join();
			logger.info("Database engine is down");
		} catch (InterruptedException e) {
			logger.error("Waiting for shutdown of database engine interrupted"); 
		}
	}
	
	public synchronized void trigger() {
		logger.debug("DatabaseEngine triggered");
		triggerFlag = true;
		notify();
	}
	
	public void init() throws MeasurementCollectorException {
		timer = new Timer("DatabaseEngineTrigger");
		timer.schedule(new TriggerTimer(this), 0, period * 1000);
	}
	
	private String createStatementFromDataObject(ADataObject ado) {
		return "";
	}
	
	@Override
	public synchronized void run() {
		while (! stop) {
			logger.debug("DatabaseEngine is about to wait for (regularly) " + period  + "s");
			while (! triggerFlag) {
				try {
					wait();
				} catch (InterruptedException e) {
				}
			}
			triggerFlag = false; 
			logger.debug("DatabaseEngine has received trigger");

			Connection dbCon = null;
			try {
				int itemCnt = 0;
				
				while (true) {
					PreparedStatement pstmt = null;
					try {
						ADataObject ado = queue.dequeue();
						if (ado == null) {
							logger.warn("DatabaseEngine found no data");
							break;
						}
						String stmtTxt = createStatementFromDataObject(ado);
						pstmt = dbCon.prepareStatement(stmtTxt);
						for (Object o : ado.getValues().values()) {
							
						}
						itemCnt++;
						logger.info("DatabaseEngine received (" + itemCnt + ") " + ado);
					} catch (SQLException e) {
						logger.error("SQLException in inner database engine loop", e);
					} finally {
						if (pstmt != null) {
							try {
								pstmt.close();
								pstmt = null;
							} catch (SQLException e) {
								logger.warn("SQLException when closing statement, nothing will be done");
							}
						}
					}
				}
			} catch (Exception e) {
				logger.error("Exception in outer database engine loop", e);
			} finally {
				if (dbCon ! null) {
					try {
						dbCon.close();
						dbCon = null;
					} catch (SQLException e) {
						logger.warn("SQLException when closing connection, nothing will be done");
					}
				}
			}
		}
		logger.info("Database engine is terminating");
	}
}
