/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2020 IBM Corporation. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     02/04/2013-2.5 Guy Pelletier
//       - 389090: JPA 2.1 DDL Generation Support
package org.eclipse.persistence.tools.schemaframework;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.platform.database.DatabasePlatform;
import org.eclipse.persistence.sequencing.Sequence;
import org.eclipse.persistence.sequencing.TableSequence;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.sessions.DatabaseSession;
import org.eclipse.persistence.sessions.Session;

/**
 * <b>Purpose</b>: This class is responsible for creating the tables defined in the project.
 * A specific subclass of this class is created for each project.  The specific table information
 * is defined in the subclass.
 *
 * @since TopLink 2.0
 * @author Peter Krogh
 */
public class TableCreator {
    /** Default identity generator sequence name.
     *  Copy of value from JPA: {@code MetadataProject.DEFAULT_IDENTITY_GENERATOR}. */
    public static final String DEFAULT_IDENTITY_GENERATOR = "SEQ_GEN_IDENTITY";

    /** Flag to disable table existence check before create. */
    public static boolean CHECK_EXISTENCE = true;

    protected List<TableDefinition> tableDefinitions;
    protected String name;
    protected boolean ignoreDatabaseException; //if true, DDL generation will continue even if exceptions occur

    public TableCreator() {
        this(new ArrayList<TableDefinition>());
    }

    public TableCreator(List<TableDefinition> tableDefinitions) {
        super();
        this.tableDefinitions = tableDefinitions;
    }

    /**
     * Add the table.
     */
    public void addTableDefinition(TableDefinition tableDefinition) {
        this.tableDefinitions.add(tableDefinition);
    }

    /**
     * Add a set of tables.
     */
    public void addTableDefinitions(Collection<TableDefinition> tableDefs) {
        this.tableDefinitions.addAll(tableDefs);
    }


    /**
     * Create constraints.
     */
    public void createConstraints(DatabaseSession session) {
        //CR2612669
        createConstraints(session, new SchemaManager(session));
    }

    /**
     * Create constraints.
     */
    public void createConstraints(DatabaseSession session, SchemaManager schemaManager) {
        createConstraints(session, schemaManager, true);
    }

    /**
     * Create constraints.
     */
    public void createConstraints(DatabaseSession session, SchemaManager schemaManager, boolean build) {
        createConstraints(getTableDefinitions(), session, schemaManager, build);
    }

    /**
     * Create constraints.
     */
    public void createConstraints(List<TableDefinition> tables, DatabaseSession session, SchemaManager schemaManager, boolean build) {
        buildConstraints(schemaManager, build);

        // Unique constraints should be generated before foreign key constraints,
        // because foreign key constraints can reference unique constraints
        for (TableDefinition table : tables) {
            try {
                schemaManager.createUniqueConstraints(table);
            } catch (DatabaseException ex) {
                if (!shouldIgnoreDatabaseException()) {
                    throw ex;
                }
            }
        }

        for (TableDefinition table : tables) {
            try {
                schemaManager.createForeignConstraints(table);
            } catch (DatabaseException ex) {
                if (!shouldIgnoreDatabaseException()) {
                    throw ex;
                }
            }
        }
    }

    /**
     * This creates the tables on the database.
     * If the table already exists this will fail.
     */
    public void createTables(org.eclipse.persistence.sessions.DatabaseSession session) {
        //CR2612669
        createTables(session, new SchemaManager(session));
    }

    /**
     * This creates the tables on the database.
     * If the table already exists this will fail.
     */
    public void createTables(DatabaseSession session, SchemaManager schemaManager) {
        createTables(session, schemaManager, true);
    }

    /**
     * This creates the tables on the database.
     * If the table already exists this will fail.
     */
    public void createTables(DatabaseSession session, SchemaManager schemaManager, boolean build) {
        createTables(session, schemaManager, build, true, true, true);
    }

    /**
     * This creates the tables on the database.
     * If the table already exists this will fail.
     * @param session Active database session.
     * @param schemaManager Database schema manipulation manager.
     * @param build Whether to build constraints.
     * @param check Whether to check for tables existence.
     * @param createSequenceTables Whether to create sequence tables.
     * @param createSequences Whether to create sequences.
     */
    public void createTables(final DatabaseSession session, final SchemaManager schemaManager, final boolean build,
            final boolean check, final boolean createSequenceTables, final boolean createSequences) {
        buildConstraints(schemaManager, build);

        final String sequenceTableName = getSequenceTableName(session);
        final List<TableDefinition> missingTables = new ArrayList<>();
        for (TableDefinition table : getTableDefinitions()) {
            // Must not create sequence table as done in createSequences.
            if (!table.getName().equals(sequenceTableName)) {
                boolean alreadyExists = false;
                // Check if the table already exists, to avoid logging create error.
                if (check && CHECK_EXISTENCE && schemaManager.shouldWriteToDatabase()) {
                    alreadyExists = schemaManager.checkTableExists(table);
                }
                if (!alreadyExists) {
                    missingTables.add(table);
                    try {
                        schemaManager.createObject(table);
                        session.getSessionLog().log(SessionLog.FINEST, SessionLog.DDL, "default_tables_created", table.getFullName());
                    } catch (DatabaseException ex) {
                        session.getSessionLog().log(SessionLog.FINEST, SessionLog.DDL, "default_tables_already_existed", table.getFullName());
                        if (!shouldIgnoreDatabaseException()) {
                            throw ex;
                        }
                    }
                }
            }
        }

        createConstraints(missingTables, session, schemaManager, false);

        schemaManager.createOrReplaceSequences(createSequenceTables, createSequences);
        session.getDatasourcePlatform().initIdentitySequences(session, DEFAULT_IDENTITY_GENERATOR);
    }

    /**
     * Drop the table constraints from the database.
     */
    public void dropConstraints(DatabaseSession session) {
        //CR2612669
        dropConstraints(session, new SchemaManager(session));
    }

    /**
     * Drop the table constraints from the database.
     */
    public void dropConstraints(DatabaseSession session, SchemaManager schemaManager) {
        dropConstraints(session, schemaManager, true);
    }

    /**
     * Drop the table constraints from the database.
     */
    public void dropConstraints(DatabaseSession session, SchemaManager schemaManager, boolean build) {
        buildConstraints(schemaManager, build);

        for (TableDefinition table : getTableDefinitions()) {
            try {
                schemaManager.dropConstraints(table);
            } catch (DatabaseException exception) {
                //ignore
            }
        }
    }

    /**
     * Drop the tables from the database.
     */
    public void dropTables(DatabaseSession session) {
        //CR2612669
        dropTables(session, new SchemaManager(session));
    }

    /**
     * Drop the tables from the database.
     */
    public void dropTables(DatabaseSession session, SchemaManager schemaManager) {
        dropTables(session, schemaManager, true);
    }

    /**
     * Drop the tables from the database.
     * @param session Active database session.
     * @param schemaManager Database schema manipulation manager.
     * @param build Whether to build constraints.
     */
    public void dropTables(final DatabaseSession session, final SchemaManager schemaManager, final boolean build) {
        buildConstraints(schemaManager, build);

        // CR 3870467, do not log stack, or log at all if not fine
        boolean shouldLogExceptionStackTrace = session.getSessionLog().shouldLogExceptionStackTrace();
        final int level = session.getSessionLog().getLevel();
        if (shouldLogExceptionStackTrace) {
            session.getSessionLog().setShouldLogExceptionStackTrace(false);
        }
        if (level > SessionLog.FINE) {
            session.getSessionLog().setLevel(SessionLog.SEVERE);
        }
        try {
            dropConstraints(session, schemaManager, false);

            final String sequenceTableName = getSequenceTableName(session);
            List<TableDefinition> tables = getTableDefinitions();
            int trys = 1;
            if (SchemaManager.FORCE_DROP) {
                trys = 5;
            }
            while ((trys > 0) && !tables.isEmpty()) {
                trys--;
                final List<TableDefinition> failed = new ArrayList<>();
                final Set<String> tableNames = new HashSet<>(tables.size());
                for (final TableDefinition table : tables) {
                    final String tableName = table.getName();
                    // Must not create sequence table as done in createSequences.
                    if (!tableName.equals(sequenceTableName)) {
                        try {
                            schemaManager.dropObject(table);
                            tableNames.add(tableName);
                        } catch (DatabaseException exception) {
                            failed.add(table);
                            if (!shouldIgnoreDatabaseException()) {
                                throw exception;
                            }
                        }
                    }
                }
                session.getDatasourcePlatform().removeIdentitySequences(session, DEFAULT_IDENTITY_GENERATOR, tableNames);
                tables = failed;
            }
        } finally {
            if (shouldLogExceptionStackTrace) {
                session.getSessionLog().setShouldLogExceptionStackTrace(true);
            }
            if (level > SessionLog.FINE) {
                session.getSessionLog().setLevel(level);
            }
        }
    }

    /**
     * Return the name.
     */
    public String getName() {
        return name;
    }

    /**
     * Return the tables.
     */
    public List<TableDefinition> getTableDefinitions() {
        return tableDefinitions;
    }

    /**
     * Recreate the tables on the database.
     * This will drop the tables if they exist and recreate them.
     */
    public void replaceTables(DatabaseSession session) {
        replaceTables(session, new SchemaManager(session));
    }

    /**
     * Recreate the tables on the database.
     * This will drop the tables if they exist and recreate them.
     */
    public void replaceTables(DatabaseSession session, SchemaManager schemaManager) {
        replaceTables(session, schemaManager, true, true);
    }

    /**
     * Recreate the tables on the database.
     * This will drop the tables if they exist and recreate them.
     */
    public void replaceTables(DatabaseSession session, SchemaManager schemaManager, boolean createSequenceTables) {
        replaceTables(session, schemaManager, createSequenceTables, false);
    }

    /**
     * Recreate the tables on the database.
     * This will drop the tables if they exist and recreate them.
     */
    public void replaceTables(DatabaseSession session, SchemaManager schemaManager, boolean createSequenceTables, boolean createSequences) {
        replaceTablesAndConstraints(schemaManager, session, createSequenceTables, createSequences);
    }

    protected void replaceTablesAndConstraints(SchemaManager schemaManager, DatabaseSession session, boolean createSequenceTables, boolean createSequences) {
        buildConstraints(schemaManager, true);
        boolean ignore = shouldIgnoreDatabaseException();
        setIgnoreDatabaseException(true);
        try {
            dropTables(session, schemaManager, false);
        } finally {
            setIgnoreDatabaseException(ignore);
        }
        createTables(session, schemaManager, false, false, createSequenceTables, createSequences);
    }

    protected void replaceTablesAndConstraints(SchemaManager schemaManager, DatabaseSession session) {
        replaceTables(session, schemaManager, false, false);
    }

    /**
     * Convert any field constraint to constraint objects.
     */
    protected void buildConstraints(SchemaManager schemaManager, boolean build) {
        if (build) {
            for (TableDefinition table : getTableDefinitions()) {
                schemaManager.buildFieldTypes(table);
            }
        }
    }

    /**
     * Set the name.
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * Set the tables.
     */
    public void setTableDefinitions(Vector tableDefinitions) {
        this.tableDefinitions = tableDefinitions;
    }

    /**
     * Return true if DatabaseException is to be ignored.
     */
    public boolean shouldIgnoreDatabaseException() {
        return ignoreDatabaseException;
    }

    /**
     * Set flag whether DatabaseException should be ignored.
     */
    public void setIgnoreDatabaseException(boolean ignoreDatabaseException) {
        this.ignoreDatabaseException = ignoreDatabaseException;
    }

    /**
     * This returns the Sequence Table's qualified name, without delimiting.
     * @return the qualified table name
     */
    protected String getSequenceTableName(Session session) {
        String sequenceTableName = null;
        if (session.getProject().usesSequencing()) {
            Sequence sequence = session.getLogin().getDefaultSequence();
            if (sequence instanceof TableSequence) {
                sequenceTableName = ((TableSequence)sequence).getQualifiedTableName();
            }
        }
        return sequenceTableName;
    }

    /**
     * Create or extend the tables on the database.
     * This will alter existing tables to add missing fields or create the table otherwise.
     * It will also create Sequences tables and objects.
     */
    public void extendTables(DatabaseSession session, SchemaManager schemaManager) {
        extendTablesAndConstraints(schemaManager, session);
        schemaManager.createOrReplaceSequences(true, true);
    }

    protected void extendTablesAndConstraints(SchemaManager schemaManager, DatabaseSession session) {
        buildConstraints(schemaManager, true);
        boolean ignore = shouldIgnoreDatabaseException();
        setIgnoreDatabaseException(true);
        try {
            extendTables(session, schemaManager, false);
        } finally {
            setIgnoreDatabaseException(ignore);
        }
    }

    /**
     * This creates/extends the tables on the database.
     * @param session Active database session.
     * @param schemaManager Database schema manipulation manager.
     * @param build Whether to build constraints.
     */
    public void extendTables(final DatabaseSession session, final SchemaManager schemaManager, final boolean build) {
        buildConstraints(schemaManager, build);

        final String sequenceTableName = getSequenceTableName(session);
        for (final TableDefinition table : getTableDefinitions()) {
            // Must not create sequence table as done in createSequences.
            if (!table.getName().equals(sequenceTableName)) {
                final AbstractSession abstractSession = (AbstractSession) session;
                boolean alreadyExists = false;
                // Check if the table already exists, to avoid logging create error.
                if (CHECK_EXISTENCE && schemaManager.shouldWriteToDatabase()) {
                    alreadyExists = schemaManager.checkTableExists(table);
                }
                DatabaseException createTableException = null;
                if (!alreadyExists) {
                    //assume table does not exist
                    try {
                        schemaManager.createObject(table);
                        session.getSessionLog().log(SessionLog.FINEST, SessionLog.DDL, "default_tables_created", table.getFullName());
                    } catch (final DatabaseException exception) {
                        createTableException = exception;
                        alreadyExists = true;
                    }
                }
                if (alreadyExists) {
                    //Assume the table exists, so lookup the column info

                    //While SQL is case insensitive, getColumnInfo is and will not return the table info unless the name is passed in
                    //as it is stored internally.
                    String tableName = table.getTable()==null? table.getName(): table.getTable().getName();
                    final boolean usesDelimiting = (table.getTable()!=null && table.getTable().shouldUseDelimiters());
                    List<DatabaseRecord> columnInfo = null;

                    //I need the actual table catalog, schema and tableName for getTableInfo.
                    columnInfo = abstractSession.getAccessor().getColumnInfo(null, null, tableName, null, abstractSession);

                    if (!usesDelimiting && (columnInfo == null || columnInfo.isEmpty()) ) {
                        tableName = tableName.toUpperCase();
                        columnInfo = abstractSession.getAccessor().getColumnInfo(null, null, tableName, null, abstractSession);
                        if (( columnInfo == null || columnInfo.isEmpty()) ){
                            tableName = tableName.toLowerCase();
                            columnInfo = abstractSession.getAccessor().getColumnInfo(null, null, tableName, null, abstractSession);
                        }
                    }
                    if (columnInfo != null && !columnInfo.isEmpty()) {
                        //Table exists, add individual fields as necessary

                        //hash the table's existing columns by name
                        final Map<DatabaseField, DatabaseRecord> columns = new HashMap(columnInfo.size());
                        final DatabaseField columnNameLookupField = new DatabaseField("COLUMN_NAME");
                        final DatabaseField schemaLookupField = new DatabaseField("TABLE_SCHEM");
                        boolean schemaMatchFound = false;
                        // Determine the probably schema for the table, this is a heuristic, so should not cause issues if wrong.
                        String qualifier = table.getQualifier();
                        if ((qualifier == null) || (qualifier.length() == 0)) {
                            qualifier = session.getDatasourcePlatform().getTableQualifier();
                            if ((qualifier == null) || (qualifier.length() == 0)) {
                                qualifier = session.getLogin().getUserName();
                                // Oracle DB DS defined in WLS does not contain user name so it's stored in platform.
                                if ((qualifier == null) || (qualifier.length() == 0)) {
                                    final DatabasePlatform platform = session.getPlatform();
                                    if (platform.supportsConnectionUserName()) {
                                        qualifier = platform.getConnectionUserName();
                                    }
                                }
                            }
                        }
                        final boolean checkSchema = (qualifier != null) && (qualifier.length() > 0);
                        for (final DatabaseRecord record : columnInfo) {
                            final String fieldName = (String)record.get(columnNameLookupField);
                            if (fieldName != null && fieldName.length() > 0) {
                                final DatabaseField column = new DatabaseField(fieldName);
                                if (session.getPlatform().shouldForceFieldNamesToUpperCase()) {
                                    column.useUpperCaseForComparisons(true);
                                }
                                final String schema = (String)record.get(schemaLookupField);
                                // Check the schema as well.  Ignore columns for other schema if a schema match is found.
                                if (schemaMatchFound) {
                                    if (qualifier.equalsIgnoreCase(schema)) {
                                        columns.put(column,  record);
                                    }
                                } else {
                                    if (checkSchema) {
                                        if (qualifier.equalsIgnoreCase(schema)) {
                                            schemaMatchFound = true;
                                            // Remove unmatched columns from other schemas.
                                            columns.clear();
                                        }
                                    }
                                    // If none of the schemas match what is expected, assume what is expected is wrong, and use all columns.
                                    columns.put(column,  record);
                                }
                            }
                        }

                        //Go through each field we need to have in the table to see if it already exists
                        for (final FieldDefinition fieldDef : table.getFields()){
                            DatabaseField dbField = fieldDef.getDatabaseField();
                            if ( dbField == null ) {
                                dbField = new DatabaseField(fieldDef.getName());
                            }
                            if (columns.get(dbField)== null) {
                                //field does not exist so add it to the table
                                try {
                                    table.addFieldOnDatabase(abstractSession, fieldDef);
                                } catch (final DatabaseException addFieldEx) {
                                    session.getSessionLog().log(SessionLog.FINEST,  SessionLog.DDL, "cannot_add_field_to_table", dbField.getName(), table.getFullName(), addFieldEx.getMessage());
                                    if (!shouldIgnoreDatabaseException()) {
                                        throw addFieldEx;
                                    }
                                }
                            }
                        }
                    } else if (createTableException != null) {
                        session.getSessionLog().log(SessionLog.FINEST, SessionLog.DDL, "cannot_create_table", table.getFullName(), createTableException.getMessage());
                        if (!shouldIgnoreDatabaseException()) {
                            throw createTableException;
                        }
                    }
                }
            }
        }
        createConstraints(session, schemaManager, false);

        schemaManager.createSequences();
        session.getDatasourcePlatform().initIdentitySequences(session, DEFAULT_IDENTITY_GENERATOR);

    }
}
