package db.migration;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import no.valg.valgnatt.common.ValgnattException;
import no.valg.valgnatt.database.Konstanter;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.flywaydb.core.api.migration.jdbc.JdbcMigration;
import org.postgresql.PGConnection;
import org.postgresql.copy.CopyManager;
import org.postgresql.core.BaseConnection;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

public class V20150000_002__Baseline_Load implements JdbcMigration {

    private static final Logger LOG = LogManager.getLogger(V20150000_002__Baseline_Load.class);

    private static String initialdata;

    public static void setInitialdata(String initialdata) {
        V20150000_002__Baseline_Load.initialdata = initialdata;
    }

    @Override
    public void migrate(Connection connection) throws SQLException, IOException {
        Resource[] resources = getResources();

        LOG.info("Laster inn data i tilstand");
        try (Statement statement = connection.createStatement()) {
            // hvilke grunnlagsdata som blir brukt skrives her og sjekkes i GrunnlagsdataCache
            statement.executeUpdate("insert into tilstand values('initialdata', '" + initialdata + "')");
            // systemet starter ved første gangs oppstart default i prognosemodus og sperrefrist slått på
            statement.executeUpdate("INSERT INTO tilstand VALUES('prognose', 'sann')");
            statement.executeUpdate("INSERT INTO tilstand VALUES('sperrefrist-offentlig', 'sann')");
            statement.executeUpdate("INSERT INTO tilstand VALUES('sperrefrist-media', 'sann')");

            BaseConnection base = getBaseConnection(connection);
            CopyManager cm = new CopyManager(base);
            for (Resource resource : resources) {
                BufferedReader br = new BufferedReader(new InputStreamReader(resource.getInputStream()));
                String colNames = br.readLine().replace(';', ',');
                br.close();
                InputStream is = resource.getInputStream();
                String tableName = resource.getFilename().substring(0, resource.getFilename().indexOf('.'));
                LOG.info("Laster inn data i " + tableName);
                cm.copyIn("COPY " + tableName + " (" + colNames + ") FROM STDIN WITH (FORMAT CSV, HEADER, DELIMITER ';')", is);
                is.close();
            }
        }
    }

    private BaseConnection getBaseConnection(Connection connection) {
        if (connection instanceof PGConnection) {
            return (BaseConnection) connection;
        }
        try {
            Method method = (connection.getClass()).getMethod("getUnderlyingConnection");
            return (BaseConnection) method.invoke(connection);
        } catch (Exception e) {
            throw new ValgnattException(e);
        }
    }

    private Resource[] getResources() throws IOException {
        Resource[] resources;
        if (Konstanter.AUTOOPPSETT_INITIALDATA.equals(initialdata)) {
            resources = new PathMatchingResourcePatternResolver().getResources("file:" + Konstanter.AUTOOPPSETT_INITIALDATAKATALOG + "/*.csv");
            LOG.info("Bruker data fra " + Konstanter.AUTOOPPSETT_INITIALDATAKATALOG);
        } else {
            resources = new PathMatchingResourcePatternResolver().getResources("classpath:db/initialdata/" + initialdata + "/*.csv");
            LOG.info("Bruker data fra classpath:db/initialdata/" + initialdata);
        }

        if (resources == null || resources.length == 0) {
            throw new ValgnattException("Fant ingen CSV-filer.");
        }
        return resources;
    }

}
