/*
 * 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.guacamole.auth.mysql.conf;

import java.io.File;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.guacamole.auth.jdbc.security.PasswordPolicy;
import org.apache.ibatis.exceptions.PersistenceException;
import org.apache.ibatis.session.SqlSession;

/**
 * A MySQL-specific implementation of JDBCEnvironment provides database
 * properties specifically for MySQL.
 */
public class MySQLEnvironment extends JDBCEnvironment {

    /**
     * Logger for this class.
     */
    private static final Logger logger = LoggerFactory.getLogger(MySQLEnvironment.class);

    /**
     * The earliest version of MariaDB that supported recursive CTEs.
     */
    private static final MySQLVersion MARIADB_SUPPORTS_CTE = new MySQLVersion(10, 2, 2, true);

    /**
     * The earliest version of MySQL that supported recursive CTEs.
     */
    private static final MySQLVersion MYSQL_SUPPORTS_CTE = new MySQLVersion(8, 0, 1, false);

    /**
     * The default MySQL-compatible driver to use, if not specified.
     */
    private static final MySQLDriver DEFAULT_DRIVER = MySQLDriver.MYSQL;
    
    /**
     * The default host to connect to, if MYSQL_HOSTNAME is not specified.
     */
    private static final String DEFAULT_HOSTNAME = "localhost";

    /**
     * The default port to connect to, if MYSQL_PORT is not specified.
     */
    private static final int DEFAULT_PORT = 3306;

    /**
     * Whether a database user account is required by default for authentication
     * to succeed.
     */
    private static final boolean DEFAULT_USER_REQUIRED = false;

    /**
     * The default value for the maximum number of connections to be
     * allowed to the Guacamole server overall.
     */
    private final int DEFAULT_ABSOLUTE_MAX_CONNECTIONS = 0;

    /**
     * The default value for the default maximum number of connections to be
     * allowed per user to any one connection.
     */
    private final int DEFAULT_MAX_CONNECTIONS_PER_USER = 1;

    /**
     * The default value for the default maximum number of connections to be
     * allowed per user to any one connection group.
     */
    private final int DEFAULT_MAX_GROUP_CONNECTIONS_PER_USER = 1;

    /**
     * The default value for the default maximum number of connections to be
     * allowed to any one connection.
     */
    private final int DEFAULT_MAX_CONNECTIONS = 0;

    /**
     * The default value for the default maximum number of connections to be
     * allowed to any one connection group.
     */
    private final int DEFAULT_MAX_GROUP_CONNECTIONS = 0;
    
    /**
     * The default SSL mode for connecting to MySQL servers.
     */
    private final MySQLSSLMode DEFAULT_SSL_MODE = MySQLSSLMode.DISABLED;

    /**
     * Constructs a new MySQLEnvironment, providing access to MySQL-specific
     * configuration options.
     * 
     * @throws GuacamoleException 
     *     If an error occurs while setting up the underlying JDBCEnvironment
     *     or while parsing legacy MySQL configuration options.
     */
    public MySQLEnvironment() throws GuacamoleException {

        // Init underlying JDBC environment
        super();

    }

    @Override
    public boolean isUserRequired() throws GuacamoleException {
        return getProperty(
            MySQLGuacamoleProperties.MYSQL_USER_REQUIRED,
            DEFAULT_USER_REQUIRED
        );
    }

    @Override
    public int getAbsoluteMaxConnections() throws GuacamoleException {
        return getProperty(MySQLGuacamoleProperties.MYSQL_ABSOLUTE_MAX_CONNECTIONS,
            DEFAULT_ABSOLUTE_MAX_CONNECTIONS
        );
    }

    @Override
    public int getDefaultMaxConnections() throws GuacamoleException {
        return getProperty(
            MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_CONNECTIONS,
            DEFAULT_MAX_CONNECTIONS
        );
    }

    @Override
    public int getDefaultMaxGroupConnections() throws GuacamoleException {
        return getProperty(
            MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_GROUP_CONNECTIONS,
            DEFAULT_MAX_GROUP_CONNECTIONS
        );
    }

    @Override
    public int getDefaultMaxConnectionsPerUser() throws GuacamoleException {
        return getProperty(
            MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_CONNECTIONS_PER_USER,
            DEFAULT_MAX_CONNECTIONS_PER_USER
        );
    }

    @Override
    public int getDefaultMaxGroupConnectionsPerUser() throws GuacamoleException {
        return getProperty(
            MySQLGuacamoleProperties.MYSQL_DEFAULT_MAX_GROUP_CONNECTIONS_PER_USER,
            DEFAULT_MAX_GROUP_CONNECTIONS_PER_USER
        );
    }

    @Override
    public PasswordPolicy getPasswordPolicy() {
        return new MySQLPasswordPolicy(this);
    }

    /**
     * Returns the MySQL driver that will be used to talk to the MySQL-compatible
     * database server hosting the Guacamole Client database.  If unspecified
     * a default value of MySQL will be used.
     * 
     * @return
     *     The MySQL driver that will be used to communicate with the MySQL-
     *     compatible server.
     * 
     * @throws GuacamoleException 
     *     If guacamole.properties cannot be parsed.
     */
    public MySQLDriver getMySQLDriver() throws GuacamoleException {
        return getProperty(
            MySQLGuacamoleProperties.MYSQL_DRIVER,
            DEFAULT_DRIVER
        );
    }
    
    /**
     * Returns the hostname of the MySQL server hosting the Guacamole
     * authentication tables. If unspecified, this will be "localhost".
     * 
     * @return
     *     The URL of the MySQL server.
     *
     * @throws GuacamoleException 
     *     If an error occurs while retrieving the property value.
     */
    public String getMySQLHostname() throws GuacamoleException {
        return getProperty(
            MySQLGuacamoleProperties.MYSQL_HOSTNAME,
            DEFAULT_HOSTNAME
        );
    }
    
    /**
     * Returns the port number of the MySQL server hosting the Guacamole
     * authentication tables. If unspecified, this will be the default MySQL
     * port of 3306.
     * 
     * @return
     *     The port number of the MySQL server.
     *
     * @throws GuacamoleException 
     *     If an error occurs while retrieving the property value.
     */
    public int getMySQLPort() throws GuacamoleException {
        return getProperty(MySQLGuacamoleProperties.MYSQL_PORT, DEFAULT_PORT);
    }
    
    /**
     * Returns the name of the MySQL database containing the Guacamole 
     * authentication tables.
     * 
     * @return
     *     The name of the MySQL database.
     *
     * @throws GuacamoleException 
     *     If an error occurs while retrieving the property value, or if the
     *     value was not set, as this property is required.
     */
    public String getMySQLDatabase() throws GuacamoleException {
        return getRequiredProperty(MySQLGuacamoleProperties.MYSQL_DATABASE);
    }
    
    /**
     * Returns the username that should be used when authenticating with the
     * MySQL database containing the Guacamole authentication tables.
     * 
     * @return
     *     The username for the MySQL database.
     *
     * @throws GuacamoleException 
     *     If an error occurs while retrieving the property value, or if the
     *     value was not set, as this property is required.
     */
    public String getMySQLUsername() throws GuacamoleException {
        return getRequiredProperty(MySQLGuacamoleProperties.MYSQL_USERNAME);
    }
    
    /**
     * Returns the password that should be used when authenticating with the
     * MySQL database containing the Guacamole authentication tables.
     * 
     * @return
     *     The password for the MySQL database.
     *
     * @throws GuacamoleException 
     *     If an error occurs while retrieving the property value, or if the
     *     value was not set, as this property is required.
     */
    public String getMySQLPassword() throws GuacamoleException {
        return getRequiredProperty(MySQLGuacamoleProperties.MYSQL_PASSWORD);
    }

    @Override
    public boolean isRecursiveQuerySupported(SqlSession session) {

        // Retrieve database version string from JDBC connection
        String versionString;
        try {
            Connection connection = session.getConnection();
            DatabaseMetaData metaData = connection.getMetaData();
            versionString = metaData.getDatabaseProductVersion();
        }
        catch (SQLException e) {
            throw new PersistenceException("Cannot determine whether "
                    + "MySQL / MariaDB supports recursive queries.", e);
        }

        try {

            // Parse MySQL / MariaDB version from version string
            MySQLVersion version = new MySQLVersion(versionString);
            logger.debug("Database recognized as {}.", version);

            // Recursive queries are supported for MariaDB 10.2.2+ and
            // MySQL 8.0.1+
            return version.isAtLeast(MARIADB_SUPPORTS_CTE)
                || version.isAtLeast(MYSQL_SUPPORTS_CTE);

        }
        catch (IllegalArgumentException e) {
            logger.debug("Unrecognized MySQL / MariaDB version string: "
                    + "\"{}\". Assuming database engine does not support "
                    + "recursive queries.", session);
            return false;
        }

    }
    
    /**
     * Return the MySQL SSL mode as configured in guacamole.properties, or the
     * default value of DISABLED if not configured.
     * 
     * @return
     *     The SSL mode to use when connecting to the MySQL server.
     * 
     * @throws GuacamoleException 
     *     If an error occurs retrieving the property value.
     */
    public MySQLSSLMode getMySQLSSLMode() throws GuacamoleException {
        return getProperty(
                MySQLGuacamoleProperties.MYSQL_SSL_MODE,
                DEFAULT_SSL_MODE);
    }
    
    /**
     * Returns the File where the trusted certificate store is located as
     * configured in guacamole.properties, or null if no value has been
     * configured.  The trusted certificate store is used to validate server
     * certificates when making SSL connections to MySQL servers.
     * 
     * @return
     *     The File where the trusted certificate store is located, or null
     *     if the value has not been configured.
     * 
     * @throws GuacamoleException
     *     If guacamole.properties cannot be parsed.
     */
    public File getMySQLSSLTrustStore() throws GuacamoleException {
        return getProperty(MySQLGuacamoleProperties.MYSQL_SSL_TRUST_STORE);
    }
    
    /**
     * Returns the password used to access the trusted certificate store as
     * configured in guacamole.properties, or null if no password has been
     * specified.
     * 
     * @return
     *     The password used to access the trusted certificate store.
     * 
     * @throws GuacamoleException 
     *     If guacamole.properties cannot be parsed.
     */
    public String getMySQLSSLTrustPassword() throws GuacamoleException {
        return getProperty(MySQLGuacamoleProperties.MYSQL_SSL_TRUST_PASSWORD);
    }
    
    /**
     * Returns the File used to store the client SSL certificate as configured
     * in guacamole.properties, or null if no value has been specified.  This
     * file will be used to load the client certificate used for SSL connections
     * to MySQL servers, if the SSL connection is so configured to require
     * client certificate authentication.
     * 
     * @return
     *     The File where the client SSL certificate is stored.
     * 
     * @throws GuacamoleException 
     *     If guacamole.properties cannot be parsed.
     */
    public File getMySQLSSLClientStore() throws GuacamoleException {
        return getProperty(MySQLGuacamoleProperties.MYSQL_SSL_TRUST_STORE);
    }
    
    /**
     * Returns the password used to access the client certificate store as
     * configured in guacamole.properties, or null if no value has been
     * specified.
     * 
     * @return
     *     The password used to access the client SSL certificate store.
     * 
     * @throws GuacamoleException 
     *     If guacamole.properties cannot be parsed.
     */
    public String getMYSQLSSLClientPassword() throws GuacamoleException {
        return getProperty(MySQLGuacamoleProperties.MYSQL_SSL_TRUST_PASSWORD);
    }
    
    @Override
    public boolean autoCreateAbsentAccounts() throws GuacamoleException {
        return getProperty(MySQLGuacamoleProperties.MYSQL_AUTO_CREATE_ACCOUNTS,
                false);
    }

}
