package com.novoda.sqlite.impl;

import com.novoda.sqlite.grammar.SQLiteLexer;
import com.novoda.sqlite.grammar.SQLiteParser;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;

/**
 * Parsing .sql files and get single statements suitable for insertion.
 */
public class SQLFile {

    private static final String NEW_LINE = "\n";
    private static final String SEMICOLON = ";";

    private List<String> statements;

    public void parse(Reader in) throws IOException {
        String sqlContent = getStringFromReader(in);

        SQLiteLexer lexer = new SQLiteLexer(new ANTLRInputStream(sqlContent));
        SQLiteParser parser = new SQLiteParser(new CommonTokenStream(lexer));
        List<SQLiteParser.Sql_stmtContext> statementListContext = parser.parse().sql_stmt_list(0).sql_stmt();

        this.statements = new ArrayList<String>(statementListContext.size());
        for (SQLiteParser.Sql_stmtContext statement : statementListContext) {
            int startIndex = statement.getStart().getStartIndex();
            int stopIndex = statement.getStop().getStopIndex();
            String textStatement = sqlContent.substring(startIndex, stopIndex + 1) + SEMICOLON;
            this.statements.add(textStatement);
        }
    }

    private String getStringFromReader(Reader reader) throws IOException {
        StringBuilder stringBuilder = new StringBuilder();
        String line;

        BufferedReader bufferedReader = new BufferedReader(reader);
        while ((line = bufferedReader.readLine()) != null) {
            stringBuilder.append(line).append(NEW_LINE);
        }
        bufferedReader.close();

        return stringBuilder.toString();
    }

    public List<String> getStatements() {
        return statements;
    }

    public static List<String> statementsFrom(File sqlFile) throws IOException {
        FileReader reader = null;
        try {
            reader = new FileReader(sqlFile);
            return statementsFrom(reader);
        } finally {
            if (reader != null) {
                reader.close();
            }
        }
    }

    public static List<String> statementsFrom(Reader reader) throws IOException {
        SQLFile file = new SQLFile();
        file.parse(reader);
        return file.getStatements();
    }
}

@@ -901,16 +901,69 @@
 lexer));
+%0A%0A        // parse() contains a list of sql_stmt_list
 %0A       
@@ -985,24 +985,29 @@
 ser.Sql_stmt
+_list
 Context%3E sta
@@ -1059,22 +1059,352 @@
 ist(
-0).sql_stmt();
+);%0A%0A        // every sql_stmt_list contains one or more sql_stmt, we need to flatten it%0A        List%3CSQLiteParser.Sql_stmtContext%3E statementList = new ArrayList%3CSQLiteParser.Sql_stmtContext%3E();%0A        for (SQLiteParser.Sql_stmt_listContext statements : statementListContext) %7B%0A            statementList.addAll(statements.sql_stmt());%0A        %7D
 %0A%0A  
@@ -1462,23 +1462,16 @@
 mentList
-Context
 .size())
@@ -1531,39 +1531,32 @@
  : statementList
-Context
 ) %7B%0A            

Flatten all statements in multiple statement lists