package com.batix.rundeck.plugins;

import com.batix.rundeck.core.AnsibleDescribable;
import com.batix.rundeck.core.AnsibleException.AnsibleFailureReason;
import com.batix.rundeck.core.AnsibleRunner;
import com.batix.rundeck.core.AnsibleRunnerBuilder;
import com.dtolabs.rundeck.core.common.INodeEntry;
import com.dtolabs.rundeck.core.common.IRundeckProject;
import com.dtolabs.rundeck.core.execution.ExecutionContext;
import com.dtolabs.rundeck.core.execution.impl.jsch.JschScpFileCopier;
import com.dtolabs.rundeck.core.execution.service.DestinationFileCopier;
import com.dtolabs.rundeck.core.execution.service.FileCopierException;
import com.dtolabs.rundeck.core.plugins.Plugin;
import com.dtolabs.rundeck.core.plugins.configuration.Description;
import com.dtolabs.rundeck.core.plugins.configuration.ConfigurationException;
import com.dtolabs.rundeck.plugins.ServiceNameConstants;
import com.dtolabs.rundeck.plugins.util.DescriptionBuilder;

import java.util.HashMap;
import java.util.Map;
import java.io.File;
import java.io.InputStream;

@Plugin(name = AnsibleFileCopier.SERVICE_PROVIDER_NAME, service = ServiceNameConstants.FileCopier)
public class AnsibleFileCopier implements DestinationFileCopier, AnsibleDescribable {

  public static final String SERVICE_PROVIDER_NAME = "com.batix.rundeck.plugins.AnsibleFileCopier";

  public static Description DESC = null;

  static {
        DescriptionBuilder builder = DescriptionBuilder.builder();
        builder.name(SERVICE_PROVIDER_NAME);
        builder.title("Ansible File Copier");
        builder.description("Sends a file to a node via the copy module.");
        builder.property(SSH_AUTH_TYPE_PROP);
        builder.property(SSH_USER_PROP);
        builder.property(SSH_PASSWORD_STORAGE_PROP);
        builder.property(SSH_KEY_FILE_PROP); 
        builder.property(SSH_KEY_STORAGE_PROP); 
        builder.property(SSH_TIMEOUT_PROP);
        builder.property(BECOME_PROP);
        builder.property(BECOME_AUTH_TYPE_PROP);
        builder.property(BECOME_USER_PROP);
        builder.property(BECOME_PASSWORD_STORAGE_PROP);
        DESC=builder.build();
  }

  @Override
  public String copyFileStream(ExecutionContext context, InputStream input, INodeEntry node, String destination) throws FileCopierException {
    return doFileCopy(context, null, input, null, node, destination);
  }

  @Override
  public String copyFile(ExecutionContext context, File file, INodeEntry node, String destination) throws FileCopierException {
    return doFileCopy(context, file, null, null, node, destination);
  }

  @Override
  public String copyScriptContent(ExecutionContext context, String script, INodeEntry node, String destination) throws FileCopierException {
    return doFileCopy(context, null, null, script, node, destination);
  }

  @Override
  public String copyFileStream(ExecutionContext context, InputStream input, INodeEntry node) throws FileCopierException {
    return doFileCopy(context, null, input, null, node, null);
  }

  @Override
  public String copyFile(ExecutionContext context, File file, INodeEntry node) throws FileCopierException {
    return doFileCopy(context, file, null, null, node, null);
  }

  @Override
  public String copyScriptContent(ExecutionContext context, String script, INodeEntry node) throws FileCopierException {
    return doFileCopy(context, null, null, script, node, null);
  }

  private String doFileCopy(
    final ExecutionContext context,
    final File scriptFile,
    final InputStream input,
    final String script,
    final INodeEntry node,
    String destinationPath
  ) throws FileCopierException {

    AnsibleRunner runner = null;

    IRundeckProject project = context.getFramework().getFrameworkProjectMgr().getFrameworkProject(context.getFrameworkProject());

    if (destinationPath == null) {
      String identity = (context.getDataContext() != null && context.getDataContext().get("job") != null) ?
                        context.getDataContext().get("job").get("execid") : null;

      destinationPath = JschScpFileCopier.generateRemoteFilepathForNode(
        node,
        project,
        context.getFramework(),
        scriptFile != null ? scriptFile.getName() : "dispatch-script",
        null,
        identity
      );
    }

    File localTempFile = scriptFile != null ?
      scriptFile : JschScpFileCopier.writeTempFile(context, null, input, script);

    String cmdArgs = "src='" + localTempFile.getAbsolutePath() + "' dest='" + destinationPath + "'";

    Map<String, Object> jobConf = new HashMap<String, Object>();
    jobConf.put(AnsibleDescribable.ANSIBLE_MODULE,"copy");
    jobConf.put(AnsibleDescribable.ANSIBLE_MODULE_ARGS,cmdArgs.toString());
    jobConf.put(AnsibleDescribable.ANSIBLE_LIMIT,node.getNodename());

    if ("true".equals(System.getProperty("ansible.debug"))) {
      jobConf.put(AnsibleDescribable.ANSIBLE_DEBUG,"True");
    } else {
      jobConf.put(AnsibleDescribable.ANSIBLE_DEBUG,"False");
    }

    AnsibleRunnerBuilder builder = new AnsibleRunnerBuilder(node, context, context.getFramework(), jobConf);


    try {
        runner = builder.buildAnsibleRunner();  
    } catch (ConfigurationException e) {
          throw new FileCopierException("Error configuring Ansible.",AnsibleFailureReason.ParseArgumentsError, e);
    }

    try {
          runner.run();
    } catch (Exception e) {
          throw new FileCopierException("Error running Ansible.", AnsibleFailureReason.AnsibleError, e);
    }

    return destinationPath;
  }

  @Override
  public Description getDescription() {
    return DESC;
  }
}


@@ -533,27 +533,16 @@
 service.
-Destination
 FileCopi
@@ -718,22 +718,33 @@
 uration.
-Descri
+ConfigurationExce
 ption;%0Ai
@@ -796,33 +796,22 @@
 uration.
-ConfigurationExce
+Descri
 ption;%0Ai
@@ -943,91 +943,91 @@
 ava.
-util.HashMap;%0Aimport java.util.Map;%0Aimport java.io.File;%0Aimport java.io.InputStream
+io.File;%0Aimport java.io.InputStream;%0Aimport java.util.HashMap;%0Aimport java.util.Map
 ;%0A%0A@
@@ -1170,19 +1170,8 @@
 nts 
-Destination
 File
@@ -2766,599 +2766,8 @@
  %7D%0A%0A
-  @Override%0A  public String copyFileStream(ExecutionContext context, InputStream input, INodeEntry node) throws FileCopierException %7B%0A    return doFileCopy(context, null, input, null, node, null);%0A  %7D%0A%0A  @Override%0A  public String copyFile(ExecutionContext context, File file, INodeEntry node) throws FileCopierException %7B%0A    return doFileCopy(context, file, null, null, node, null);%0A  %7D%0A%0A  @Override%0A  public String copyScriptContent(ExecutionContext context, String script, INodeEntry node) throws FileCopierException %7B%0A    return doFileCopy(context, null, null, script, node, null);%0A  %7D%0A%0A
   pr

update FileCopier interface