package liquibase.diff.output.changelog.core;

import liquibase.CatalogAndSchema;
import liquibase.change.Change;
import liquibase.change.core.AddPrimaryKeyChange;
import liquibase.database.Database;
import liquibase.database.core.AbstractDb2Database;
import liquibase.database.core.MSSQLDatabase;
import liquibase.database.core.OracleDatabase;
import liquibase.database.core.PostgresDatabase;
import liquibase.diff.output.DiffOutputControl;
import liquibase.diff.output.changelog.AbstractChangeGenerator;
import liquibase.diff.output.changelog.ChangeGeneratorChain;
import liquibase.diff.output.changelog.ChangeGeneratorFactory;
import liquibase.diff.output.changelog.MissingObjectChangeGenerator;
import liquibase.exception.UnexpectedLiquibaseException;
import liquibase.snapshot.SnapshotGeneratorFactory;
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.*;

import java.util.ArrayList;
import java.util.List;

public class MissingPrimaryKeyChangeGenerator extends AbstractChangeGenerator implements MissingObjectChangeGenerator {

    @Override
    public int getPriority(Class<? extends DatabaseObject> objectType, Database database) {
        if (PrimaryKey.class.isAssignableFrom(objectType)) {
            return PRIORITY_DEFAULT;
        }
        return PRIORITY_NONE;

    }

    @Override
    public Class<? extends DatabaseObject>[] runAfterTypes() {
        return new Class[]{
                Table.class,
                Column.class
        };

    }

    @Override
    public Class<? extends DatabaseObject>[] runBeforeTypes() {
        return new Class[]{
                Index.class
        };
    }

    @Override
    public Change[] fixMissing(DatabaseObject missingObject, DiffOutputControl control, Database referenceDatabase, Database comparisonDatabase, ChangeGeneratorChain chain) {
        List<Change> returnList = new ArrayList<Change>();

        PrimaryKey pk = (PrimaryKey) missingObject;

        AddPrimaryKeyChange change = createAddPrimaryKeyChange();
        change.setTableName(pk.getTable().getName());
        if (control.getIncludeCatalog()) {
            change.setCatalogName(pk.getTable().getSchema().getCatalogName());
        }
        if (control.getIncludeSchema()) {
            change.setSchemaName(pk.getTable().getSchema().getName());
        }
        change.setConstraintName(pk.getName());
        change.setColumnNames(pk.getColumnNames());
        if (control.getIncludeTablespace()) {
            change.setTablespace(pk.getTablespace());
        }

        if (referenceDatabase instanceof MSSQLDatabase && pk.getBackingIndex() != null && pk.getBackingIndex().getClustered() != null && !pk.getBackingIndex().getClustered()) {
            change.setClustered(false);
        }
        if (referenceDatabase instanceof PostgresDatabase && pk.getBackingIndex() != null && pk.getBackingIndex().getClustered() != null && pk.getBackingIndex().getClustered()) {
            change.setClustered(true);
        }

        //handleMissingIndexChange(control, referenceDatabase, comparisonDatabase, returnList, pk, change);

        returnList.add(change);

        return returnList.toArray(new Change[returnList.size()]);

    }

    /**
     * DAT-876 was fixed but what is the reason of doing this logic ?! Nathan, Steve please review !
     * Also please DO NOT APPROVE THIS pull request with this comment also I'm not sure about side effects
     * Thank you in advance !
     */
    @SuppressWarnings("unused")
    private void handleMissingIndexChange(DiffOutputControl control, Database referenceDatabase, Database comparisonDatabase, List<Change> returnList, PrimaryKey pk, AddPrimaryKeyChange change) {
        if (comparisonDatabase instanceof OracleDatabase
                || (comparisonDatabase instanceof AbstractDb2Database && pk.getBackingIndex() != null && !comparisonDatabase.isSystemObject(pk.getBackingIndex()))) {
            Index backingIndex = pk.getBackingIndex();
            if (backingIndex != null && backingIndex.getName() != null) {
                try {
                    if (!control.getIncludeCatalog() && !control.getIncludeSchema()) {
                        CatalogAndSchema schema = comparisonDatabase.getDefaultSchema().customize(comparisonDatabase);
                        backingIndex.getTable().setSchema(schema.getCatalogName(), schema.getSchemaName()); //set table schema so it is found in the correct schema
                    }
                    if (referenceDatabase.equals(comparisonDatabase) || !SnapshotGeneratorFactory.getInstance().has(backingIndex, comparisonDatabase)) {
                        Change[] fixes = ChangeGeneratorFactory.getInstance().fixMissing(backingIndex, control, referenceDatabase, comparisonDatabase);

                        if (fixes != null) {
                            for (Change fix : fixes) {
                                if (fix != null) {
                                    returnList.add(fix);
                                }
                            }
                        }

                    }
                } catch (Exception e) {
                    throw new UnexpectedLiquibaseException(e);
                }


                change.setForIndexName(backingIndex.getName());
                Schema schema = backingIndex.getSchema();
                if (schema != null) {
                    if (control.getIncludeCatalog()) {
                        change.setForIndexCatalogName(schema.getCatalogName());
                    }
                    if (control.getIncludeSchema()) {
                        change.setForIndexSchemaName(schema.getName());
                    }
                }
            }
        }
        control.setAlreadyHandledMissing(pk.getBackingIndex());
    }

    protected AddPrimaryKeyChange createAddPrimaryKeyChange() {
        return new AddPrimaryKeyChange();
    }

}

@@ -2995,2784 +2995,99 @@
     
-//handleMissingIndexChange(control, referenceDatabase, comparisonDatabase, returnList, pk, change);%0A%0A        returnList.add(change);%0A%0A        return returnList.toArray(new Change%5BreturnList.size()%5D);%0A%0A    %7D%0A%0A    /**%0A     * DAT-876 was fixed but what is the reason of doing this logic ?! Nathan, Steve please review !%0A     * Also please DO NOT APPROVE THIS pull request with this comment also I'm not sure about side effects%0A     * Thank you in advance !%0A     */%0A    @SuppressWarnings(%22unused%22)%0A    private void handleMissingIndexChange(DiffOutputControl control, Database referenceDatabase, Database comparisonDatabase, List%3CChange%3E returnList, PrimaryKey pk, AddPrimaryKeyChange change) %7B%0A        if (comparisonDatabase instanceof OracleDatabase%0A                %7C%7C (comparisonDatabase instanceof AbstractDb2Database && pk.getBackingIndex() != null && !comparisonDatabase.isSystemObject(pk.getBackingIndex()))) %7B%0A            Index backingIndex = pk.getBackingIndex();%0A            if (backingIndex != null && backingIndex.getName() != null) %7B%0A                try %7B%0A                    if (!control.getIncludeCatalog() && !control.getIncludeSchema()) %7B%0A                        CatalogAndSchema schema = comparisonDatabase.getDefaultSchema().customize(comparisonDatabase);%0A                        backingIndex.getTable().setSchema(schema.getCatalogName(), schema.getSchemaName()); //set table schema so it is found in the correct schema%0A                    %7D%0A                    if (referenceDatabase.equals(comparisonDatabase) %7C%7C !SnapshotGeneratorFactory.getInstance().has(backingIndex, comparisonDatabase)) %7B%0A                        Change%5B%5D fixes = ChangeGeneratorFactory.getInstance().fixMissing(backingIndex, control, referenceDatabase, comparisonDatabase);%0A%0A                        if (fixes != null) %7B%0A                            for (Change fix : fixes) %7B%0A                                if (fix != null) %7B%0A                                    returnList.add(fix);%0A                                %7D%0A                            %7D%0A                        %7D%0A%0A                    %7D%0A                %7D catch (Exception e) %7B%0A                    throw new UnexpectedLiquibaseException(e);%0A                %7D%0A%0A%0A                change.setForIndexName(backingIndex.getName());%0A                Schema schema = backingIndex.getSchema();%0A                if (schema != null) %7B%0A                    if (control.getIncludeCatalog()) %7B%0A                        change.setForIndexCatalogName(schema.getCatalogName());%0A                    %7D%0A                    if (control.getIncludeSchema()) %7B%0A                        change.setForIndexSchemaName(schema.getName());%0A                    %7D%0A                %7D%0A            %7D%0A        %7D%0A        control.setAlreadyHandledMissing(pk.getBackingIndex());
+returnList.add(change);%0A%0A        return returnList.toArray(new Change%5BreturnList.size()%5D);%0A
 %0A   

Remove call to and implementation of handleMissingIndexChange()