/*
 * 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.java;

import static java.lang.String.format;

import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Nullable;

import org.apache.brooklyn.entity.software.base.lifecycle.ScriptHelper;
import org.apache.brooklyn.location.ssh.SshMachineLocation;
import org.apache.brooklyn.util.collections.MutableList;
import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.core.file.ArchiveBuilder;
import org.apache.brooklyn.util.core.file.ArchiveUtils;
import org.apache.brooklyn.util.core.internal.ssh.SshTool;
import org.apache.brooklyn.util.core.task.Tasks;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.net.Urls;
import org.apache.brooklyn.util.os.Os;
import org.apache.brooklyn.util.text.Strings;
import org.apache.brooklyn.util.text.StringEscapes.BashStringEscapes;

import com.google.common.base.CharMatcher;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;

/**
 * The SSH implementation of the {@link VanillaJavaAppDriver}.
 */
public class VanillaJavaAppSshDriver extends JavaSoftwareProcessSshDriver implements VanillaJavaAppDriver {

    // FIXME this should be a config, either on the entity or -- probably better -- 
    // an alternative / override timeout on the SshTool for file copy commands
    final static int NUM_RETRIES_FOR_COPYING = 4;
    
    public VanillaJavaAppSshDriver(VanillaJavaAppImpl entity, SshMachineLocation machine) {
        super(entity, machine);
    }

    @Override
    public VanillaJavaAppImpl getEntity() {
        return (VanillaJavaAppImpl) super.getEntity();
    }

    @Override
    protected String getLogFileLocation() {
        return Os.mergePathsUnix(getRunDir(), "console");
    }

    @Override
    public void install() {
        newScript(INSTALLING).execute();
    }

    @Override
    public void customize() {
        newScript(CUSTOMIZING)
                .body.append(format("mkdir -p %s/lib", getRunDir()))
                .failOnNonZeroResultCode()
                .execute();

        SshMachineLocation machine = getMachine();
        VanillaJavaApp entity = getEntity();
        for (String entry : entity.getClasspath()) {
            // If a local folder, then create archive from contents first
            if (Urls.isDirectory(entry)) {
                File jarFile = ArchiveBuilder.jar().addDirContentsAt(new File(entry), "").create();
                entry = jarFile.getAbsolutePath();
            }

            // Determine filename
            String destFile = entry.contains("?") ? entry.substring(0, entry.indexOf('?')) : entry;
            destFile = destFile.substring(destFile.lastIndexOf('/') + 1);

            ArchiveUtils.deploy(MutableMap.<String, Object>of(), entry, machine, getRunDir(), Os.mergePaths(getRunDir(), "lib"), destFile);
        }

        ScriptHelper helper = newScript(CUSTOMIZING+"-classpath")
                .body.append(String.format("ls -1 \"%s\"", Os.mergePaths(getRunDir(), "lib")))
                .gatherOutput();
        helper.setFlag(SshTool.PROP_NO_EXTRA_OUTPUT, true);
        int result = helper.execute();
        if (result != 0) {
            throw new IllegalStateException("Error listing classpath files: " + helper.getResultStderr());
        }
        String stdout = helper.getResultStdout();

        // Transform stdout into list of files in classpath
        if (Strings.isBlank(stdout)) {
            getEntity().setAttribute(VanillaJavaApp.CLASSPATH_FILES, ImmutableList.of(Os.mergePaths(getRunDir(), "lib")));
        } else {
            // FIXME Cannot handle spaces in paths properly
            Iterable<String> lines = Splitter.on(CharMatcher.BREAKING_WHITESPACE).omitEmptyStrings().trimResults().split(stdout);
            Iterable<String> files = Iterables.transform(lines, new Function<String, String>() {
                        @Override
                        public String apply(@Nullable String input) {
                            return Os.mergePathsUnix(getRunDir(), "lib", input);
                        }
                    });
            getEntity().setAttribute(VanillaJavaApp.CLASSPATH_FILES, ImmutableList.copyOf(files));
        }
    }

    public String getClasspath() {
        @SuppressWarnings("unchecked")
        List<String> files = getEntity().getAttribute(VanillaJavaApp.CLASSPATH_FILES);
        if (files == null || files.isEmpty()) {
            return null;
        } else {
            return Joiner.on(":").join(files);
        }
    }

    @Override
    public void launch() {
        String clazz = getEntity().getMainClass();
        String args = getArgs();

        newScript(MutableMap.of(USE_PID_FILE, true), LAUNCHING)
            .body.append(
                    format("echo \"launching: java $JAVA_OPTS %s %s\"", clazz, args),
                    format("java $JAVA_OPTS -cp \"%s\" %s %s >> %s/console 2>&1 </dev/null &", getClasspath(), clazz, args, getRunDir())
                )
            .execute();
    }

    public String getArgs(){
        List<Object> args = getEntity().getConfig(VanillaJavaApp.ARGS);
        StringBuilder sb = new StringBuilder();
        Iterator<Object> it = args.iterator();
        while (it.hasNext()) {
            Object argO = it.next();
            try {
                String arg = Tasks.resolveValue(argO, String.class, getEntity().getExecutionContext());
                BashStringEscapes.assertValidForDoubleQuotingInBash(arg);
                sb.append(format("\"%s\"",arg));
            } catch (Exception e) {
                throw Exceptions.propagate(e);
            }
            if (it.hasNext()) {
                sb.append(" ");
            }
        }

        return sb.toString();
    }

    @Override
    public boolean isRunning() {
        int result = newScript(MutableMap.of(USE_PID_FILE, true), CHECK_RUNNING).execute();
        return result == 0;
    }

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

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

    @Override
    protected Map getCustomJavaSystemProperties() {
        return MutableMap.builder()
                .putAll(super.getCustomJavaSystemProperties())
                .putAll(getEntity().getJvmDefines())
                .build();
    }

    @Override
    protected List<String> getCustomJavaConfigOptions() {
        return MutableList.<String>builder()
                .addAll(super.getCustomJavaConfigOptions())
                .addAll(getEntity().getJvmXArgs())
                .build();
    }

    @Override
    public Map<String,String> getShellEnvironment() {
        return MutableMap.<String,String>builder()
                .putAll(super.getShellEnvironment())
                .putIfNotNull("CLASSPATH", getClasspath())
                .build();
    }
}
