/*
 * 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.brooklyn.entity.database.mariadb;

import static java.lang.String.format;
import static org.apache.brooklyn.util.JavaGroovyEquivalents.groovyTruth;
import static org.apache.brooklyn.util.ssh.BashCommands.commandsToDownloadUrlsAs;
import static org.apache.brooklyn.util.ssh.BashCommands.installPackage;
import static org.apache.brooklyn.util.ssh.BashCommands.ok;

import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.brooklyn.entity.database.DatastoreMixins;
import org.apache.brooklyn.entity.software.base.AbstractSoftwareProcessSshDriver;
import org.apache.brooklyn.api.location.OsDetails;
import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks;
import org.apache.brooklyn.core.entity.Attributes;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.location.ssh.SshMachineLocation;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.core.task.DynamicTasks;
import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper;
import org.apache.brooklyn.util.net.Urls;
import org.apache.brooklyn.util.os.Os;
import org.apache.brooklyn.util.ssh.BashCommands;
import org.apache.brooklyn.util.text.Identifiers;
import org.apache.brooklyn.util.text.Strings;
import org.apache.brooklyn.util.time.CountdownTimer;
import org.apache.brooklyn.util.time.Duration;

import com.google.common.collect.ImmutableMap;

/**
 * The SSH implementation of the {@link MariaDbDriver}.
 */
public class MariaDbSshDriver extends AbstractSoftwareProcessSshDriver implements MariaDbDriver {

    public static final Logger log = LoggerFactory.getLogger(MariaDbSshDriver.class);

    public MariaDbSshDriver(MariaDbNodeImpl entity, SshMachineLocation machine) {
        super(entity, machine);

        entity.sensors().set(Attributes.LOG_FILE_LOCATION, getLogFile());
    }

    public String getOsTag() {
        OsDetails os = getLocation().getOsDetails();
        // NOTE: cannot rely on OsDetails.isLinux() to return true for all linux flavours, so
        // explicitly test for unsupported OSes, otherwise assume generic linux.
        if (os == null) return "linux-i686";
        if (os.isWindows() || os.isMac())
            throw new UnsupportedOperationException("only support linux versions just now; OS details: " + os);
        return (os.is64bit() ? "linux-x86_64" : "linux-i686");
    }

    public String getDownloadParentDir() {
        // NOTE: cannot rely on OsDetails.isLinux() to return true for all linux flavours, so
        // explicitly test for unsupported OSes, otherwise assume generic linux.
        OsDetails os = getLocation().getOsDetails();
        if (os == null) return "bintar-linux-x86";
        if (os.isWindows() || os.isMac())
            throw new UnsupportedOperationException("only support linux versions just now; OS details: " + os);
        return (os.is64bit() ? "bintar-linux-x86_64" : "bintar-linux-x86");
    }

    public String getMirrorUrl() {
        return entity.getConfig(MariaDbNode.MIRROR_URL);
    }

    public String getBaseDir() { return getExpandedInstallDir(); }

    public String getDataDir() {
        String result = entity.getConfig(MariaDbNode.DATA_DIR);
        return (result == null) ? "." : result;
    }

    public String getLogFile() {
        return Urls.mergePaths(getRunDir(), "console.log");
    }

    public String getConfigFile() {
        return "my.cnf";
    }

    public String getInstallFilename() {
        return String.format("mariadb-%s-%s.tar.gz", getVersion(), getOsTag());
    }

    @Override
    public void prepare() {
        resolver = Entities.newDownloader(this, ImmutableMap.of("filename", getInstallFilename()));
        setExpandedInstallDir(Os.mergePaths(getInstallDir(), resolver.getUnpackedDirectoryName(format("mariadb-%s-%s", getVersion(), getOsTag()))));
    }

    @Override
    public void install() {
        List<String> urls = resolver.getTargets();
        String saveAs = resolver.getFilename();

        List<String> commands = new LinkedList<String>();
        commands.add(BashCommands.INSTALL_TAR);
        commands.add(BashCommands.INSTALL_CURL);

        commands.add("echo installing extra packages");
        commands.add(installPackage(ImmutableMap.of("yum", "libgcc_s.so.1"), null));
        commands.add(installPackage(ImmutableMap.of("yum", "libaio.so.1 libncurses.so.5", "apt", "libaio1 libaio-dev"), null));

        // these deps are needed on some OS versions but others don't need them so ignore failures (ok(...))
        commands.add(ok(installPackage(ImmutableMap.of("yum", "libaio", "apt", "ia32-libs"), null)));
        commands.add("echo finished installing extra packages");

        commands.addAll(commandsToDownloadUrlsAs(urls, saveAs));
        commands.add(format("tar xfvz %s", saveAs));

        newScript(INSTALLING).body.append(commands).execute();
    }

    @Override
    public MariaDbNodeImpl getEntity() { return (MariaDbNodeImpl) super.getEntity(); }
    public int getPort() { return getEntity().getPort(); }
    public String getSocketUid() { return getEntity().getSocketUid(); }
    public String getPassword() { return getEntity().getPassword(); }

    @Override
    public void customize() {
        copyDatabaseConfigScript();

        newScript(CUSTOMIZING)
            .updateTaskAndFailOnNonZeroResultCode()
            .body.append(
                "chmod 600 "+getConfigFile(),
                getBaseDir()+"/scripts/mysql_install_db "+
                    "--basedir="+getBaseDir()+" --datadir="+getDataDir()+" "+
                    "--defaults-file="+getConfigFile())
            .execute();

        // launch, then we will configure it
        launch();

        CountdownTimer timer = Duration.seconds(20).countdownTimer();
        boolean hasCreationScript = copyDatabaseCreationScript();
        timer.waitForExpiryUnchecked();

        DynamicTasks.queue(
            SshEffectorTasks.ssh(
                "cd "+getRunDir(),
                getBaseDir()+"/bin/mysqladmin --defaults-file="+getConfigFile()+" --password= password "+getPassword()
            ).summary("setting password"));

        if (hasCreationScript)
            executeScriptFromInstalledFileAsync("creation-script.sql");

        // not sure necessary to stop then subsequently launch, but seems safest
        // (if skipping, use a flag in launch to indicate we've just launched it)
        stop();
    }

    private void copyDatabaseConfigScript() {
        newScript(CUSTOMIZING).execute();  //create the directory

        String configScriptContents = processTemplate(entity.getAttribute(MariaDbNode.TEMPLATE_CONFIGURATION_URL));
        Reader configContents = new StringReader(configScriptContents);

        getMachine().copyTo(configContents, Urls.mergePaths(getRunDir(), getConfigFile()));
    }

    private boolean copyDatabaseCreationScript() {
        InputStream creationScript = DatastoreMixins.getDatabaseCreationScript(entity);
        if (creationScript==null) return false;
        getMachine().copyTo(creationScript, getRunDir() + "/creation-script.sql");
        return true;
    }

    public String getMariaDbServerOptionsString() {
        Map<String, Object> options = entity.getConfig(MariaDbNode.MARIADB_SERVER_CONF);
        StringBuilder result = new StringBuilder();
        if (groovyTruth(options)) {
            for (Map.Entry<String, Object> entry : options.entrySet()) {
                result.append(entry.getKey());
                String value = entry.getValue().toString();
                if (!Strings.isEmpty(value)) {
                    result.append(" = ").append(value);
                }
                result.append('\n');
            }
        }
        return result.toString();
    }

    @Override
    public void launch() {
        newScript(MutableMap.of("usePidFile", true), LAUNCHING)
            .updateTaskAndFailOnNonZeroResultCode()
            .body.append(format("nohup %s/bin/mysqld --defaults-file=%s --user=`whoami` > %s 2>&1 < /dev/null &", getBaseDir(), getConfigFile(), getLogFile()))
            .execute();
    }

    @Override
    public boolean isRunning() {
        return newScript(MutableMap.of("usePidFile", false), CHECK_RUNNING)
            .body.append(getStatusCmd())
            .execute() == 0;
    }

    @Override
    public void stop() {
        newScript(MutableMap.of("usePidFile", true), STOPPING).execute();
    }

    @Override
    public void kill() {
        newScript(MutableMap.of("usePidFile", true), KILLING).execute();
    }

    @Override
    public String getStatusCmd() {
        return format("%s/bin/mysqladmin --defaults-file=%s status", getExpandedInstallDir(), Urls.mergePaths(getRunDir(), getConfigFile()));
    }

    @Override
    public ProcessTaskWrapper<Integer> executeScriptAsync(String commands) {
        String filename = "mariadb-commands-"+Identifiers.makeRandomId(8);
        DynamicTasks.queue(SshEffectorTasks.put(Urls.mergePaths(getRunDir(), filename)).contents(commands).summary("copying datastore script to execute "+filename));
        return executeScriptFromInstalledFileAsync(filename);
    }

    public ProcessTaskWrapper<Integer> executeScriptFromInstalledFileAsync(String filenameAlreadyInstalledAtServer) {
        return DynamicTasks.queue(
                SshEffectorTasks.ssh(
                                "cd "+getRunDir(),
                                getBaseDir()+"/bin/mysql --defaults-file="+getConfigFile()+" < "+filenameAlreadyInstalledAtServer)
                        .requiringExitCodeZero()
                        .summary("executing datastore script "+filenameAlreadyInstalledAtServer));
    }

}
