/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.ignite.console.agent.handlers;

import java.io.BufferedReader;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import io.socket.emitter.Emitter;
import org.apache.ignite.console.agent.AgentConfiguration;
import org.apache.ignite.console.agent.db.DbMetadataReader;
import org.apache.ignite.console.agent.db.DbSchema;
import org.apache.ignite.console.agent.db.DbTable;
import org.apache.ignite.console.demo.AgentMetadataDemo;
import org.apache.log4j.Logger;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.ignite.console.agent.AgentUtils.resolvePath;

/**
 * API to extract database metadata.
 */
public class DatabaseListener {
    /** */
    private static final Logger log = Logger.getLogger(DatabaseListener.class.getName());

    /** */
    private static final String IMPLEMENTATION_VERSION = "Implementation-Version";

    /** */
    private static final String BUNDLE_VERSION = "Bundle-Version";

    /** */
    private final File driversFolder;

    /** */
    private final DbMetadataReader dbMetaReader;

    /** */
    private final AbstractListener schemasLsnr = new AbstractListener() {
        @Override public Object execute(Map<String, Object> args) throws Exception {
            String driverPath = null;

            if (args.containsKey("jdbcDriverJar"))
                driverPath = args.get("jdbcDriverJar").toString();

            if (!args.containsKey("jdbcDriverClass"))
                throw new IllegalArgumentException("Missing driverClass in arguments: " + args);

            String driverCls = args.get("jdbcDriverClass").toString();

            if (!args.containsKey("jdbcUrl"))
                throw new IllegalArgumentException("Missing url in arguments: " + args);

            String url = args.get("jdbcUrl").toString();

            if (!args.containsKey("info"))
                throw new IllegalArgumentException("Missing info in arguments: " + args);

            Properties info = new Properties();

            info.putAll((Map)args.get("info"));

            return schemas(driverPath, driverCls, url, info);
        }
    };

    /** */
    private final AbstractListener metadataLsnr = new AbstractListener() {
        @Override public Object execute(Map<String, Object> args) throws Exception {
            String driverPath = null;

            if (args.containsKey("jdbcDriverJar"))
                driverPath = args.get("jdbcDriverJar").toString();

            if (!args.containsKey("jdbcDriverClass"))
                throw new IllegalArgumentException("Missing driverClass in arguments: " + args);

            String driverCls = args.get("jdbcDriverClass").toString();

            if (!args.containsKey("jdbcUrl"))
                throw new IllegalArgumentException("Missing url in arguments: " + args);

            String url = args.get("jdbcUrl").toString();

            if (!args.containsKey("info"))
                throw new IllegalArgumentException("Missing info in arguments: " + args);

            Properties info = new Properties();

            info.putAll((Map)args.get("info"));

            if (!args.containsKey("schemas"))
                throw new IllegalArgumentException("Missing schemas in arguments: " + args);

            List<String> schemas = (List<String>)args.get("schemas");

            if (!args.containsKey("tablesOnly"))
                throw new IllegalArgumentException("Missing tablesOnly in arguments: " + args);

            boolean tblsOnly = (boolean)args.get("tablesOnly");

            return metadata(driverPath, driverCls, url, info, schemas, tblsOnly);
        }
    };

    /** */
    private final AbstractListener availableDriversLsnr = new AbstractListener() {
        @Override public Object execute(Map<String, Object> args) {
            if (driversFolder == null) {
                log.info("JDBC drivers folder not specified, returning empty list");

                return Collections.emptyList();
            }

            if (log.isDebugEnabled())
                log.debug("Collecting JDBC drivers in folder: " + driversFolder.getPath());

            File[] list = driversFolder.listFiles(new FilenameFilter() {
                @Override public boolean accept(File dir, String name) {
                    return name.endsWith(".jar");
                }
            });

            if (list == null) {
                log.info("JDBC drivers folder has no files, returning empty list");

                return Collections.emptyList();
            }

            List<JdbcDriver> res = new ArrayList<>();

            for (File file : list) {
                try {
                    boolean win = System.getProperty("os.name").contains("win");

                    URL url = new URL("jar", null,
                        "file:" + (win ? "/" : "") + file.getPath() + "!/META-INF/services/java.sql.Driver");

                    try (
                        BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), UTF_8));
                        JarFile jar = new JarFile(file.getPath())
                    ) {
                        Manifest m = jar.getManifest();
                        Object ver = m.getMainAttributes().getValue(IMPLEMENTATION_VERSION);

                        if (ver == null)
                            ver = m.getMainAttributes().getValue(BUNDLE_VERSION);

                        String jdbcDriverCls = reader.readLine();

                        res.add(new JdbcDriver(file.getName(), jdbcDriverCls, ver != null ? ver.toString() : null));

                        if (log.isDebugEnabled())
                            log.debug("Found: [driver=" + file + ", class=" + jdbcDriverCls + "]");
                    }
                }
                catch (IOException e) {
                    res.add(new JdbcDriver(file.getName(), null, null));

                    log.info("Found: [driver=" + file + "]");
                    log.info("Failed to detect driver class: " + e.getMessage());
                }
            }

            return res;
        }
    };

    /**
     * @param cfg Config.
     */
    public DatabaseListener(AgentConfiguration cfg) {
        driversFolder = resolvePath(cfg.driversFolder() == null ? "jdbc-drivers" : cfg.driversFolder());
        dbMetaReader = new DbMetadataReader();
    }

    /**
     * @param jdbcDriverJarPath JDBC driver JAR path.
     * @param jdbcDriverCls JDBC driver class.
     * @param jdbcUrl JDBC URL.
     * @param jdbcInfo Properties to connect to database.
     * @return Connection to database.
     * @throws SQLException If failed to connect.
     */
    private Connection connect(String jdbcDriverJarPath, String jdbcDriverCls, String jdbcUrl,
        Properties jdbcInfo) throws SQLException {
        if (AgentMetadataDemo.isTestDriveUrl(jdbcUrl))
            return AgentMetadataDemo.testDrive();

        if (!new File(jdbcDriverJarPath).isAbsolute() && driversFolder != null)
            jdbcDriverJarPath = new File(driversFolder, jdbcDriverJarPath).getPath();

        return dbMetaReader.connect(jdbcDriverJarPath, jdbcDriverCls, jdbcUrl, jdbcInfo);
    }

    /**
     * @param jdbcDriverJarPath JDBC driver JAR path.
     * @param jdbcDriverCls JDBC driver class.
     * @param jdbcUrl JDBC URL.
     * @param jdbcInfo Properties to connect to database.
     * @return Collection of schema names.
     * @throws SQLException If failed to collect schemas.
     */
    protected DbSchema schemas(String jdbcDriverJarPath, String jdbcDriverCls, String jdbcUrl,
        Properties jdbcInfo) throws SQLException {
        if (log.isDebugEnabled())
            log.debug("Start collecting database schemas [drvJar=" + jdbcDriverJarPath +
                ", drvCls=" + jdbcDriverCls + ", jdbcUrl=" + jdbcUrl + "]");

        try (Connection conn = connect(jdbcDriverJarPath, jdbcDriverCls, jdbcUrl, jdbcInfo)) {
            String catalog = conn.getCatalog();

            if (catalog == null) {
                String[] parts = jdbcUrl.split("[/:=]");

                catalog = parts.length > 0 ? parts[parts.length - 1] : "NONE";
            }

            Collection<String> schemas = dbMetaReader.schemas(conn);

            if (log.isDebugEnabled())
                log.debug("Finished collection of schemas [jdbcUrl=" + jdbcUrl + ", catalog=" + catalog +
                    ", count=" + schemas.size() + "]");

            return new DbSchema(catalog, schemas);
        }
        catch (Throwable e) {
            log.error("Failed to collect schemas", e);

            throw new SQLException("Failed to collect schemas", e);
        }
    }

    /**
     * Listener for drivers.
     *
     * @return Drivers in drivers folder
     * @see AgentConfiguration#driversFolder
     */
    public Emitter.Listener availableDriversListener() {
        return availableDriversLsnr;
    }

    /**
     * Listener for schema names.
     *
     * @return Collection of schema names.
     */
    public Emitter.Listener schemasListener() {
        return schemasLsnr;
    }

    /**
     * @param jdbcDriverJarPath JDBC driver JAR path.
     * @param jdbcDriverCls JDBC driver class.
     * @param jdbcUrl JDBC URL.
     * @param jdbcInfo Properties to connect to database.
     * @param schemas List of schema names to process.
     * @param tblsOnly If {@code true} then only tables will be processed otherwise views also will be processed.
     * @return Collection of tables.
     */
    protected Collection<DbTable> metadata(String jdbcDriverJarPath, String jdbcDriverCls, String jdbcUrl,
        Properties jdbcInfo, List<String> schemas, boolean tblsOnly) throws SQLException {
        if (log.isDebugEnabled())
            log.debug("Start collecting database metadata [drvJar=" + jdbcDriverJarPath +
                ", drvCls=" + jdbcDriverCls + ", jdbcUrl=" + jdbcUrl + "]");

        try (Connection conn = connect(jdbcDriverJarPath, jdbcDriverCls, jdbcUrl, jdbcInfo)) {
            Collection<DbTable> metadata = dbMetaReader.metadata(conn, schemas, tblsOnly);

            if (log.isDebugEnabled())
                log.debug("Finished collection of metadata [jdbcUrl=" + jdbcUrl + ", count=" + metadata.size() + "]");

            return metadata;
        }
        catch (Throwable e) {
            log.error("Failed to collect metadata", e);

            throw new SQLException("Failed to collect metadata", e);
        }
    }

    /**
     * Listener for tables.
     *
     * @return Collection of tables.
     */
    public Emitter.Listener metadataListener() {
        return metadataLsnr;
    }

    /**
     * Stop handler.
     */
    public void stop() {
        availableDriversLsnr.stop();

        schemasLsnr.stop();

        metadataLsnr.stop();
    }

    /**
     * Wrapper class for later to be transformed to JSON and send to Web Console.
     */
    private static class JdbcDriver {
        /** */
        public final String jdbcDriverJar;

        /** */
        public final String jdbcDriverCls;

        /** */
        public final String jdbcDriverImplVersion;

        /**
         * @param jdbcDriverJar File name of driver jar file.
         * @param jdbcDriverCls Optional JDBC driver class.
         */
        public JdbcDriver(String jdbcDriverJar, String jdbcDriverCls, String jdbcDriverImplVersion) {
            this.jdbcDriverJar = jdbcDriverJar;
            this.jdbcDriverCls = jdbcDriverCls;
            this.jdbcDriverImplVersion = jdbcDriverImplVersion;
        }
    }
}
