/*
 * Copyright 2010-2020 Boxfuse GmbH
 *
 * Licensed 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
 *
 *         http://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.flywaydb.core.internal.database.db2;

import org.flywaydb.core.api.configuration.Configuration;
import org.flywaydb.core.internal.parser.*;

import java.io.IOException;
import java.util.List;

public class DB2Parser extends Parser {
    private static final String COMMENT_DIRECTIVE = "--#";
    private static final String SET_TERMINATOR_DIRECTIVE = COMMENT_DIRECTIVE + "SET TERMINATOR ";

    public DB2Parser(Configuration configuration, ParsingContext parsingContext) {
        super(configuration, parsingContext, COMMENT_DIRECTIVE.length());
    }

    @Override
    protected void adjustBlockDepth(ParserContext context, List<Token> tokens, Token keyword, PeekingReader reader) throws IOException {
        boolean previousTokenIsKeyword = !tokens.isEmpty() && tokens.get(tokens.size() - 1).getType() == TokenType.KEYWORD;

        int lastKeywordIndex = getLastKeywordIndex(tokens);
        String previousKeyword = lastKeywordIndex >= 0 ? tokens.get(lastKeywordIndex).getText() : null;

        lastKeywordIndex = getLastKeywordIndex(tokens, lastKeywordIndex);
        String previousPreviousToken = lastKeywordIndex >= 0 ? tokens.get(lastKeywordIndex).getText() : null;

        if (
            // BEGIN increases block depth, exception when used with ROW BEGIN
                ("BEGIN".equals(keyword.getText())
                        && (!"ROW".equals(previousKeyword)
                        || previousPreviousToken == null || "EACH".equals(previousPreviousToken)))
                        // CASE, DO, IF and REPEAT increase block depth
                        || (("CASE".equals(keyword.getText()) || "DO".equals(keyword.getText())
                        || "IF".equals(keyword.getText()) || "REPEAT".equals(keyword.getText())))) {
            // But not END IF and END WHILE
            if (!previousTokenIsKeyword || !"END".equals(previousKeyword)) {
                context.increaseBlockDepth();

            }
        } else if (
            // END decreases block depth, exception when used with ROW END
                "END".equals(keyword.getText()) && !"ROW".equals(previousKeyword)) {
            context.decreaseBlockDepth();
        }
    }

    @Override
    protected void resetDelimiter(ParserContext context) {
        // Do not reset delimiter as delimiter changes survive beyond a single statement
    }

    @Override
    protected boolean isCommentDirective(String peek) {
        return peek.startsWith(COMMENT_DIRECTIVE);
    }

    @Override
    protected Token handleCommentDirective(PeekingReader reader, ParserContext context, int pos, int line, int col) throws IOException {
        if (SET_TERMINATOR_DIRECTIVE.equals(reader.peek(SET_TERMINATOR_DIRECTIVE.length()))) {
            reader.swallow(SET_TERMINATOR_DIRECTIVE.length());
            String delimiter = reader.readUntilExcluding('\n', '\r');
            return new Token(TokenType.NEW_DELIMITER, pos, line, col, delimiter.trim(), delimiter, context.getParensDepth());
        }
        reader.swallowUntilExcluding('\n', '\r');
        return new Token(TokenType.COMMENT, pos, line, col, null, null, context.getParensDepth());
    }
}
@@ -801,16 +801,48 @@
 il.List;
+%0Aimport java.util.regex.Pattern;
 %0A%0Apublic
@@ -1189,32 +1189,289 @@
 ngth());%0A    %7D%0A%0A
+    private static final Pattern CREATE_IF_NOT_EXISTS = Pattern.compile(%0A            %22.*CREATE%5C%5Cs(%5B%5E%5C%5Cs%5D+%5C%5Cs)%7B0,2%7DIF%5C%5CsNOT%5C%5CsEXISTS%22);%0A    private static final Pattern DROP_IF_EXISTS = Pattern.compile(%0A            %22.*DROP%5C%5Cs(%5B%5E%5C%5Cs%5D+%5C%5Cs)%7B0,2%7DIF%5C%5CsEXISTS%22);%0A%0A
     @Override%0A  
@@ -2943,16 +2943,17 @@
         
+(
 %22END%22.eq
@@ -3002,32 +3002,201 @@
 reviousKeyword))
+%0A                        %7C%7C doTokensMatchPattern(tokens, keyword, CREATE_IF_NOT_EXISTS)%0A                        %7C%7C doTokensMatchPattern(tokens, keyword, DROP_IF_EXISTS))
  %7B%0A            c

Fix #2748 Add support for DROP IF EXISTS and CREATE IF NOT EXISTS to the DB2 parser