package org.jenkinsci.plugins.radargun;

import hudson.AbortException;
import hudson.EnvVars;
import hudson.Extension;
import hudson.Util;
import hudson.model.EnvironmentSpecific;
import hudson.model.TaskListener;
import hudson.model.Node;
import hudson.remoting.Callable;
import hudson.remoting.VirtualChannel;
import hudson.slaves.NodeSpecific;
import hudson.tools.ToolDescriptor;
import hudson.tools.ToolInstaller;
import hudson.tools.ToolProperty;
import hudson.tools.ToolInstallation;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;

import jenkins.model.Jenkins;

import org.jenkinsci.plugins.radargun.model.RgScriptConfig;
import org.jenkinsci.remoting.RoleChecker;
import org.kohsuke.stapler.DataBoundConstructor;

/**
 * RadarGunInstallation
 * 
 * @author vjuranek
 * 
 */
public class RadarGunInstallation extends ToolInstallation implements EnvironmentSpecific<RadarGunInstallation>,
        NodeSpecific<RadarGunInstallation> {

    @DataBoundConstructor
    public RadarGunInstallation(String name, String home, List<? extends ToolProperty<?>> properties) {
        super(name, home, properties);
    }

    @Override
    public RadarGunInstallation forEnvironment(EnvVars environment) {
        return new RadarGunInstallation(getName(), environment.expand(getHome()), getProperties().toList());
    }

    @Override
    public RadarGunInstallation forNode(Node node, TaskListener log) throws IOException, InterruptedException {
        return new RadarGunInstallation(getName(), translateFor(node, log), getProperties().toList());
    }

    /**
     * Gets the executable path of this RadarGun installation on the given target system.
     */
    public String getExecutable(final RgScriptConfig executable, VirtualChannel channel) throws IOException,
            InterruptedException {
        return channel.call(new Callable<String, IOException>() {

            public String call() throws IOException {
                File exec = getExeFile(executable);
                if (exec.exists()) {
                    return exec.getPath();
                }
                //abort build if we cannot locate RG executables
                throw new AbortException(
                        String.format(
                                "Cannot resolver path to executable %s, something wrong with your RG installation? Exiting ... ",
                                executable.getScriptName()));
            }

            @Override
            public void checkRoles(RoleChecker arg0) throws SecurityException {
                //no-op
            }
        });
    }

    private File getExeFile(final RgScriptConfig executable) {
        // TODO expand installation with t.translate(node, EnvVars.getRemote(checkChannel()))
        String rgHome = Util.replaceMacro(getHome(), EnvVars.masterEnvVars); // TODO - env var on slave??
        File binDir = new File(rgHome, "bin");
        return new File(binDir, executable.getScriptName());
    }

    @Extension
    public static class DescriptorImpl extends ToolDescriptor<RadarGunInstallation> {

        public DescriptorImpl() {
        }

        @Override
        public String getDisplayName() {
            return "RadarGun";
        }

        @Override
        public List<? extends ToolInstaller> getDefaultInstallers() {
            return Collections.singletonList(new RadarGunInstaller(null));
        }

        @Override
        public RadarGunInstallation[] getInstallations() {
            List<RadarGunInstallation> rdi = Jenkins.getInstance()
                    .getDescriptorByType(RadarGunBuilder.DescriptorImpl.class).getInstallations();
            RadarGunInstallation[] rdia = new RadarGunInstallation[rdi.size()];
            return rdi.toArray(rdia);
        }

        @Override
        public void setInstallations(RadarGunInstallation... installations) {
            Jenkins.getInstance().getDescriptorByType(RadarGunBuilder.DescriptorImpl.class)
                    .setInstallations(installations);
        }

    }

    private static final long serialVersionUID = 1L;

}

@@ -237,41 +237,8 @@
 de;%0A
-import hudson.remoting.Callable;%0A
 impo
@@ -311,44 +311,8 @@
 ic;%0A
-import hudson.tools.ToolDescriptor;%0A
 impo
@@ -376,16 +376,52 @@
 operty;%0A
+import hudson.tools.ToolDescriptor;%0A
 import h
@@ -583,16 +583,63 @@
 Jenkins;
+%0Aimport jenkins.security.MasterToSlaveCallable;
 %0A%0Aimport
@@ -696,51 +696,8 @@
 ig;%0A
-import org.jenkinsci.remoting.RoleChecker;%0A
 impo
@@ -1855,16 +1855,29 @@
 all(new 
+MasterToSlave
 Callable
@@ -2476,135 +2476,57 @@
     
-@Override%0A            public void checkRoles(RoleChecker arg0) throws SecurityException %7B%0A                //no-op%0A            %7D
+private static final long serialVersionUID = 1L;%0A
 %0A   

Check properly Callable roles