/*
 * 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 org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
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<>());
    }

    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(List<TableDefinition> 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<AbstractRecord> 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, AbstractRecord> 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 AbstractRecord 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);

    }
}
