/*
 * Copyright (C) 2018, 2019 Andrew Gegg
 *
 *	This file is part of the Garden Notebook application
 *
 * The Garden Notebook application is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/gpl.html>.
 */

/*
	Change log
	2.6.0   First version
 */
package uk.co.gardennotebook.mysql;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.EntryMessage;
import uk.co.gardennotebook.spi.GNDBException;
import uk.co.gardennotebook.spi.NotebookEntryType;

/**
 *  Various utility functions to support the Builder and Lister classes.
 * 
*	@author	Andy Gegg
*	@version	2.6.0
*	@since	2.6.0
 */
final class StoryLineIndexUtils
{
    
	private static final Logger LOGGER = LogManager.getLogger();

	static synchronized boolean hasAncestor(NotebookEntryType key, int id) throws GNDBException
	{
		EntryMessage log4jEntryMsg = LOGGER.traceEntry("StoryLineIndexUtils: hasAncestor(key: {}, id: {})", key.type(), id);

		boolean gotOne = false;
		StringBuilder query = new StringBuilder();
		switch (DBConnection.DB_IN_USE)
		{
			case MariaDB, MySQL -> query.append("select exists (select storylineindexid ").
					append("from storylineindex ").
					append("where descendantId = ").append(id).append(" and ").
					append("descendantType = '").append(key.type()).append("' and depth > 0) as fred");
			case hsqldb -> query.append("select exists (select storylineindexid ").
					append("from storylineindex ").
					append("where descendantId = ").append(id).append(" and ").
					append("descendantType = '").append(key.type()).append("' and depth > 0) as fred ").
					append(" from (values(0))");
			case MSSQLServer -> query.append("select CASE WHEN EXISTS (select storylineindexid ").
					append("from storylineindex ").
					append("where descendantId = ").append(id).append(" and ").
					append("descendantType = '").append(key.type()).append("' and depth > 0) THEN 1 ELSE 0 END as fred");
			default -> {
				LOGGER.error("hasAncestor(): no known rdbms");
				throw new GNDBException(new IllegalStateException("StoryLineIndexLister: hasAncestor(): no known RDBMS"));
			}
		}
LOGGER.debug("StoryLineIndexUtils: hasAncestor(): query: {}", query);
		try (	Connection conn = DBConnection.getConnection();
				Statement stmt = conn.createStatement();
                ResultSet rs = stmt.executeQuery(query.toString()); )
		{
			while (rs.next())
			{
				gotOne = gotOne || rs.getBoolean("fred");
			}
LOGGER.debug("StoryLineIndexUtils: hasAncestor(): gotOne: {}", gotOne);
		}catch (SQLException ex) {
			LOGGER.error("StoryLineIndexUtils: hasAncestor(): SQLException: errorCode: {}, SQLstate: {}, message: {}", ex.getErrorCode(), ex.getSQLState(), ex.getMessage());
			throw new GNDBException(ex, ex.getErrorCode(), ex.getSQLState());
		}
		return LOGGER.traceExit("hasAncestor()", gotOne);
	}	//	hasAncestor()

	static synchronized boolean hasDescendant(NotebookEntryType key, int id) throws GNDBException
	{
		EntryMessage log4jEntryMsg = LOGGER.traceEntry("StoryLineIndexUtils: hasDescendant(key: {}, id: {})", key.type(), id);

		boolean gotOne = false;
		StringBuilder query = new StringBuilder();
		switch (DBConnection.DB_IN_USE)
		{
			case MariaDB, MySQL -> query.append("select exists (select storylineindexid ").
					append("from storylineindex ").
					append("where ancestorId = ").append(id).append(" and ").
					append("ancestorType = '").append(key.type()).append("' and depth > 0) as fred");
			case hsqldb -> query.append("select exists (select storylineindexid ").
					append("from storylineindex ").
					append("where ancestorId = ").append(id).append(" and ").
					append("ancestorType = '").append(key.type()).append("' and depth > 0) as fred").
					append(" from (values(0))");
			case MSSQLServer -> query.append("select CASE WHEN EXISTS (select storylineindexid ").
					append("from storylineindex ").
					append("where ancestorId = ").append(id).append(" and ").
					append("ancestorType = '").append(key.type()).append("' and depth > 0) THEN 1 ELSE 0 END as fred");
			default -> {
				LOGGER.error("hasDescendant(): no known rdbms");
				throw new GNDBException(new IllegalStateException("StoryLineIndexLister: hasDescendant(): no known RDBMS"));
			}
		}
LOGGER.debug("StoryLineIndexUtils: hasDescendant(): query: {}", query);
		try (	Connection conn = DBConnection.getConnection();
				Statement stmt = conn.createStatement();	)
		{
			ResultSet rs = stmt.executeQuery(query.toString());
			while (rs.next())
			{
				gotOne = gotOne || rs.getBoolean("fred");
			}
LOGGER.debug("StoryLineIndexUtils: hasDescendant(): gotOne: {}", gotOne);
			stmt.close();
		}catch (SQLException ex) {
			LOGGER.error("StoryLineIndexUtils: hasDescendant(): SQLException: errorCode: {}, SQLstate: {}, message: {}", ex.getErrorCode(), ex.getSQLState(), ex.getMessage());
			throw new GNDBException(ex, ex.getErrorCode(), ex.getSQLState());
		}
		return LOGGER.traceExit("hasDescendant()", gotOne);
	}	//	hasDescendant()

}
