/*****************************************************************
 *   Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 ****************************************************************/

package org.apache.cayenne.access;

import org.apache.cayenne.ashwood.AshwoodEntitySorter;
import org.apache.cayenne.conn.DataSourceInfo;
import org.apache.cayenne.datasource.DriverDataSource;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.PkGenerator;
import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.log.JdbcEventLogger;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbJoin;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.map.EntitySorter;
import org.apache.cayenne.validation.SimpleValidationFailure;
import org.apache.cayenne.validation.ValidationResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;

/**
 * Utility class that generates database schema based on Cayenne mapping. It is
 * a logical counterpart of DbLoader class.
 */
public class DbGenerator {

	private static final Logger logObj = LoggerFactory.getLogger(DbGenerator.class);

	protected DbAdapter adapter;
	protected DataMap map;

	// optional DataDomain needed for correct FK generation in cross-db
	// situations
	protected DataDomain domain;

	protected JdbcEventLogger jdbcEventLogger;

	// stores generated SQL statements
	protected Map<String, Collection<String>> dropTables;
	protected Map<String, String> createTables;
	protected Map<String, List<String>> createConstraints;
	protected List<String> createPK;
	protected List<String> dropPK;

	/**
	 * Contains all DbEntities ordered considering their interdependencies.
	 * DerivedDbEntities are filtered out of this list.
	 */
	protected List<DbEntity> dbEntitiesInInsertOrder;
	protected List<DbEntity> dbEntitiesRequiringAutoPK;

	protected boolean shouldDropTables;
	protected boolean shouldCreateTables;
	protected boolean shouldDropPKSupport;
	protected boolean shouldCreatePKSupport;
	protected boolean shouldCreateFKConstraints;

	protected ValidationResult failures;

	/**
	 * @since 3.1
	 */
	public DbGenerator(DbAdapter adapter, DataMap map, JdbcEventLogger logger) {
		this(adapter, map, logger, Collections.<DbEntity> emptyList());
	}

	/**
	 * @since 3.1
	 */
	public DbGenerator(DbAdapter adapter, DataMap map, JdbcEventLogger logger, Collection<DbEntity> excludedEntities) {
		this(adapter, map, excludedEntities, null, logger);
	}

	/**
	 * Creates and initializes new DbGenerator instance.
	 * 
	 * @param adapter
	 *            DbAdapter corresponding to the database
	 * @param map
	 *            DataMap whose entities will be used in schema generation
	 * @param excludedEntities
	 *            entities that should be ignored during schema generation
	 * @param domain
	 *            optional DataDomain used to detect cross-database
	 *            relationships.
	 * @since 3.1
	 */
	public DbGenerator(DbAdapter adapter, DataMap map, Collection<DbEntity> excludedEntities, DataDomain domain,
			JdbcEventLogger logger) {
		// sanity check
		if (adapter == null) {
			throw new IllegalArgumentException("Adapter must not be null.");
		}

		if (map == null) {
			throw new IllegalArgumentException("DataMap must not be null.");
		}

		this.domain = domain;
		this.map = map;
		this.adapter = adapter;
		this.jdbcEventLogger = logger;

		prepareDbEntities(excludedEntities);
		resetToDefaults();
		buildStatements();
	}

	protected void resetToDefaults() {
		this.shouldDropTables = false;
		this.shouldDropPKSupport = false;
		this.shouldCreatePKSupport = true;
		this.shouldCreateTables = true;
		this.shouldCreateFKConstraints = true;
	}

	/**
	 * Creates and stores internally a set of statements for database schema
	 * creation, ignoring configured schema creation preferences. Statements are
	 * NOT executed in this method.
	 */
	protected void buildStatements() {
		dropTables = new HashMap<>();
		createTables = new HashMap<>();
		createConstraints = new HashMap<>();

		DbAdapter adapter = getAdapter();
		for (final DbEntity dbe : this.dbEntitiesInInsertOrder) {

			String name = dbe.getName();

			// build "DROP TABLE"
			dropTables.put(name, adapter.dropTableStatements(dbe));

			// build "CREATE TABLE"
			createTables.put(name, adapter.createTable(dbe));

			// build constraints
			createConstraints.put(name, createConstraintsQueries(dbe));
		}

		PkGenerator pkGenerator = adapter.getPkGenerator();
		dropPK = pkGenerator.dropAutoPkStatements(dbEntitiesRequiringAutoPK);
		createPK = pkGenerator.createAutoPkStatements(dbEntitiesRequiringAutoPK);
	}

	/**
	 * Returns <code>true</code> if there is nothing to be done by this
	 * generator. If <code>respectConfiguredSettings</code> is <code>true</code>
	 * , checks are done applying currently configured settings, otherwise check
	 * is done, assuming that all possible generated objects.
	 */
	public boolean isEmpty(boolean respectConfiguredSettings) {
		if (dbEntitiesInInsertOrder.isEmpty() && dbEntitiesRequiringAutoPK.isEmpty()) {
			return true;
		}

		if (!respectConfiguredSettings) {
			return false;
		}

		return !(shouldDropTables || shouldCreateTables || shouldCreateFKConstraints || shouldCreatePKSupport || shouldDropPKSupport);
	}

	/** Returns DbAdapter associated with this DbGenerator. */
	public DbAdapter getAdapter() {
		return adapter;
	}

	/**
	 * Returns a list of all schema statements that should be executed with the
	 * current configuration.
	 */
	public List<String> configuredStatements() {
		List<String> list = new ArrayList<>();

		if (shouldDropTables) {
			ListIterator<DbEntity> it = dbEntitiesInInsertOrder.listIterator(dbEntitiesInInsertOrder.size());
			while (it.hasPrevious()) {
				DbEntity ent = it.previous();
				list.addAll(dropTables.get(ent.getName()));
			}
		}

		if (shouldCreateTables) {
			for (final DbEntity ent : dbEntitiesInInsertOrder) {
				list.add(createTables.get(ent.getName()));
			}
		}

		if (shouldCreateFKConstraints) {
			for (final DbEntity ent : dbEntitiesInInsertOrder) {
				List<String> fks = createConstraints.get(ent.getName());
				list.addAll(fks);
			}
		}

		if (shouldDropPKSupport) {
			list.addAll(dropPK);
		}

		if (shouldCreatePKSupport) {
			list.addAll(createPK);
		}

		return list;
	}

	/**
	 * Creates a temporary DataSource out of DataSourceInfo and invokes
	 * <code>public void runGenerator(DataSource ds)</code>.
	 */
	public void runGenerator(DataSourceInfo dsi) throws Exception {
		this.failures = null;

		// do a pre-check. Maybe there is no need to run anything
		// and therefore no need to create a connection
		if (isEmpty(true)) {
			return;
		}

		Driver driver = (Driver) Class.forName(dsi.getJdbcDriver()).newInstance();
		DataSource dataSource = new DriverDataSource(driver, dsi.getDataSourceUrl(), dsi.getUserName(),
				dsi.getPassword());

		runGenerator(dataSource);
	}

	/**
	 * Executes a set of commands to drop/create database objects. This is the
	 * main worker method of DbGenerator. Command set is built based on
	 * pre-configured generator settings.
	 */
	public void runGenerator(DataSource ds) throws Exception {
		this.failures = null;

		try (Connection connection = ds.getConnection()) {
			// force connection to autocommit, see CAY-2354
			boolean autoCommit = connection.getAutoCommit();
			connection.setAutoCommit(true);
			try {
				// drop tables
				if (shouldDropTables) {
					ListIterator<DbEntity> it = dbEntitiesInInsertOrder.listIterator(dbEntitiesInInsertOrder.size());
					while (it.hasPrevious()) {
						DbEntity ent = it.previous();
						for (String statement : dropTables.get(ent.getName())) {
							safeExecute(connection, statement);
						}
					}
				}

				// create tables
				List<String> createdTables = new ArrayList<>();
				if (shouldCreateTables) {
					for (final DbEntity ent : dbEntitiesInInsertOrder) {

						// only create missing tables

						safeExecute(connection, createTables.get(ent.getName()));
						createdTables.add(ent.getName());
					}
				}

				// create FK
				if (shouldCreateTables && shouldCreateFKConstraints) {
					for (DbEntity ent : dbEntitiesInInsertOrder) {

						if (createdTables.contains(ent.getName())) {
							List<String> fks = createConstraints.get(ent.getName());
							for (String fk : fks) {
								safeExecute(connection, fk);
							}
						}
					}
				}

				// drop PK
				if (shouldDropPKSupport) {
					List<String> dropAutoPKSQL = getAdapter().getPkGenerator().dropAutoPkStatements(
							dbEntitiesRequiringAutoPK);
					for (final String sql : dropAutoPKSQL) {
						safeExecute(connection, sql);
					}
				}

				// create pk
				if (shouldCreatePKSupport) {
					List<String> createAutoPKSQL = getAdapter().getPkGenerator().createAutoPkStatements(
							dbEntitiesRequiringAutoPK);
					for (final String sql : createAutoPKSQL) {
						safeExecute(connection, sql);
					}
				}

				new DbGeneratorPostprocessor().execute(connection, getAdapter());
			} finally {
				// restore connection autocommit state in case it will be recycled in some underlying pool
				connection.setAutoCommit(autoCommit);
			}
		}
	}

	/**
	 * Builds and executes a SQL statement, catching and storing SQL exceptions
	 * resulting from invalid SQL. Only non-recoverable exceptions are rethrown.
	 * 
	 * @since 1.1
	 */
	protected boolean safeExecute(Connection connection, String sql) throws SQLException {

		try (Statement statement = connection.createStatement()) {
			jdbcEventLogger.log(sql);
			statement.execute(sql);
			return true;
		} catch (SQLException ex) {
			if (this.failures == null) {
				this.failures = new ValidationResult();
			}

			failures.addFailure(new SimpleValidationFailure(sql, ex.getMessage()));
			jdbcEventLogger.logQueryError(ex);
			return false;
		}
	}

	/**
	 * Creates FK and UNIQUE constraint statements for a given table.
	 * 
	 * @since 3.0
	 */
	public List<String> createConstraintsQueries(DbEntity table) {
		List<String> list = new ArrayList<>();
		for (final DbRelationship rel : table.getRelationships()) {

			if (rel.isToMany()) {
				continue;
			}

			// skip FK to a different DB
			if (domain != null) {
				DataMap srcMap = rel.getSourceEntity().getDataMap();
				DataMap targetMap = rel.getTargetEntity().getDataMap();

				if (srcMap != null && targetMap != null && srcMap != targetMap) {
					if (domain.lookupDataNode(srcMap) != domain.lookupDataNode(targetMap)) {
						continue;
					}
				}
			}

			// create an FK CONSTRAINT only if the relationship is to PK
			// and if this is not a dependent PK

			// create UNIQUE CONSTRAINT on FK if reverse relationship is to-one

			if (rel.isToPK() && !rel.isToDependentPK()) {

				if (getAdapter().supportsUniqueConstraints()) {

					DbRelationship reverse = rel.getReverseRelationship();
					if (reverse != null && !reverse.isToMany() && !reverse.isToPK()) {

						String unique = getAdapter().createUniqueConstraint((DbEntity) rel.getSourceEntity(),
								rel.getSourceAttributes());
						if (unique != null) {
							list.add(unique);
						}
					}
				}

				String fk = getAdapter().createFkConstraint(rel);
				if (fk != null) {
					list.add(fk);
				}
			}
		}
		return list;
	}

	/**
	 * Returns an object representing a collection of failures that occurred on
	 * the last "runGenerator" invocation, or null if there were no failures.
	 * Failures usually indicate problems with generated DDL (such as
	 * "create...", "drop...", etc.) and usually happen due to the DataMap being
	 * out of sync with the database.
	 * 
	 * @since 1.1
	 */
	public ValidationResult getFailures() {
		return failures;
	}

	/**
	 * Returns whether DbGenerator is configured to create primary key support
	 * for DataMap entities.
	 */
	public boolean shouldCreatePKSupport() {
		return shouldCreatePKSupport;
	}

	/**
	 * Returns whether DbGenerator is configured to create tables for DataMap
	 * entities.
	 */
	public boolean shouldCreateTables() {
		return shouldCreateTables;
	}

	public boolean shouldDropPKSupport() {
		return shouldDropPKSupport;
	}

	public boolean shouldDropTables() {
		return shouldDropTables;
	}

	public boolean shouldCreateFKConstraints() {
		return shouldCreateFKConstraints;
	}

	public void setShouldCreatePKSupport(boolean shouldCreatePKSupport) {
		this.shouldCreatePKSupport = shouldCreatePKSupport;
	}

	public void setShouldCreateTables(boolean shouldCreateTables) {
		this.shouldCreateTables = shouldCreateTables;
	}

	public void setShouldDropPKSupport(boolean shouldDropPKSupport) {
		this.shouldDropPKSupport = shouldDropPKSupport;
	}

	public void setShouldDropTables(boolean shouldDropTables) {
		this.shouldDropTables = shouldDropTables;
	}

	public void setShouldCreateFKConstraints(boolean shouldCreateFKConstraints) {
		this.shouldCreateFKConstraints = shouldCreateFKConstraints;
	}

	/**
	 * Returns a DataDomain used by the DbGenerator to detect cross-database
	 * relationships. By default DataDomain is null.
	 * 
	 * @since 1.2
	 */
	public DataDomain getDomain() {
		return domain;
	}

	/**
	 * Helper method that orders DbEntities to satisfy referential constraints
	 * and returns an ordered list. It also filters out DerivedDbEntities.
	 */
	private void prepareDbEntities(Collection<DbEntity> excludedEntities) {
		if (excludedEntities == null) {
			excludedEntities = Collections.emptyList();
		}

		List<DbEntity> tables = new ArrayList<>();
		List<DbEntity> tablesWithAutoPk = new ArrayList<>();

		for (DbEntity nextEntity : map.getDbEntities()) {

			// do sanity checks...

			// tables with no columns are not included
			if (nextEntity.getAttributes().size() == 0) {
				logObj.info("Skipping entity with no attributes: " + nextEntity.getName());
				continue;
			}

			// check if this entity is explicitly excluded
			if (excludedEntities.contains(nextEntity)) {
				continue;
			}

			// tables with invalid DbAttributes are not included
			boolean invalidAttributes = false;
			for (final DbAttribute attr : nextEntity.getAttributes()) {
				if (attr.getType() == TypesMapping.NOT_DEFINED) {
					logObj.info("Skipping entity, attribute type is undefined: " + nextEntity.getName() + "."
							+ attr.getName());
					invalidAttributes = true;
					break;
				}
			}
			if (invalidAttributes) {
				continue;
			}

			tables.add(nextEntity);

			// check if an automatic PK generation can be potentially supported
			// in this entity. For now simply check that the key is not
			// propagated
			Iterator<DbRelationship> relationships = nextEntity.getRelationships().iterator();

			// create a copy of the original PK list,
			// since the list will be modified locally
			List<DbAttribute> pkAttributes = new ArrayList<>(nextEntity.getPrimaryKeys());
			while (pkAttributes.size() > 0 && relationships.hasNext()) {
				DbRelationship nextRelationship = relationships.next();
				if (!nextRelationship.isToMasterPK()) {
					continue;
				}

				// supposedly all source attributes of the relationship
				// to master entity must be a part of primary key,
				// so
				for (DbJoin join : nextRelationship.getJoins()) {
					pkAttributes.remove(join.getSource());
				}
			}

			// primary key is needed only if at least one of the primary key
			// attributes
			// is not propagated via relationship
			if (pkAttributes.size() > 0) {
				tablesWithAutoPk.add(nextEntity);
			}
		}

		// sort table list
		if (tables.size() > 1) {
			EntitySorter sorter = new AshwoodEntitySorter();
			sorter.setEntityResolver(new EntityResolver(Collections.singleton(map)));
			sorter.sortDbEntities(tables, false);
		}

		this.dbEntitiesInInsertOrder = tables;
		this.dbEntitiesRequiringAutoPK = tablesWithAutoPk;
	}
}
