package org.jenkinsci.plugins.emailextoverssh;

import hudson.ExtensionList;
import hudson.FilePath;
import hudson.Plugin;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Action;
import org.jenkinsci.plugins.emailextoverssh.plugins.content.AbstractEvalContent;
import org.jenkinsci.plugins.emailextoverssh.plugins.content.JellyScriptContent;
import org.jenkinsci.plugins.emailextoverssh.plugins.content.ScriptContent;
import hudson.util.FormValidation;
import hudson.util.StreamTaskListener;
import jenkins.model.Jenkins;
import org.apache.commons.lang.StringUtils;
import org.jenkinsci.lib.configprovider.ConfigProvider;
import org.jenkinsci.lib.configprovider.model.Config;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.bind.JavaScriptMethod;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;

/**
 *
 * @author acearl
 */
public class EmailExtTemplateAction implements Action {
    
    private final AbstractProject<?,?> project;

    public EmailExtTemplateAction(AbstractProject<?,?> project) {
        this.project = project;        
    }
    
    public String getIconFileName() {
        // returning null allows us to have our own action.jelly
        return null;
    }

    public String getDisplayName() {
        return Messages.EmailExtTemplateAction_DisplayName();
    }

    public String getUrlName() {
        return "templateTest";
    }   
    
    private String renderError(Exception ex) {
        StringBuilder builder = new StringBuilder();
        builder.append("<h3>An error occured trying to render the template:</h3><br/><span style=\"color:red; font-weight:bold\">")
                .append(ex.toString().replace("\n", "<br/>")).append("</span>");
        return builder.toString();
    }
    
    public FormValidation doTemplateFileCheck(@QueryParameter final String value) {
        if(!StringUtils.isEmpty(value)) {
            if(value.startsWith("managed:")) {
                return checkForManagedFile(value);
            } else {
                // first check in the default resources area...
                InputStream inputStream = Thread.currentThread().getContextClassLoader()
                		.getResourceAsStream("hudson/plugins/emailext/templates/" + value);                
                if(inputStream == null) {                
                    final File scriptsFolder = new File(Jenkins.getActiveInstance().getRootDir(), "email-templates");
                    final File scriptFile = new File(scriptsFolder, value);
                    try {
                        if(!scriptFile.exists() || !AbstractEvalContent.isChildOf(new FilePath(scriptFile), new FilePath(scriptsFolder))) {
                            return FormValidation.error("The file '" + value + "' does not exist");
                        }
                    } catch (IOException | InterruptedException e) {
                        //Don't want to expose too much info to a potential file fishing attempt
                        return FormValidation.error("I/O Error.");
                    }
                }
            }
        }
        return FormValidation.ok();
    }
    
    private FormValidation checkForManagedFile(final String value) {
        Plugin plugin = Jenkins.getActiveInstance().getPlugin("config-file-provider");
        if(plugin != null) {
            Config config = null;
            Collection<ConfigProvider> providers = getTemplateConfigProviders();
            for(ConfigProvider provider : providers) {
                for(Config c : provider.getAllConfigs()) {
                    if(c.name.equalsIgnoreCase(value)) {
                        return FormValidation.ok();
                    }                    
                }            
            }
        } else {
            return FormValidation.error(Messages.EmailExtTemplateAction_ConfigFileProviderNotAvailable());
        }
        return FormValidation.error(Messages.EmailExtTemplateAction_ManagedTemplateNotFound());
    }
    
    private static Collection<ConfigProvider> getTemplateConfigProviders() {
        Collection<ConfigProvider> providers = new ArrayList<>();
        ExtensionList<ConfigProvider> all = ConfigProvider.all();
        ConfigProvider p = all.get(GroovyTemplateConfig.GroovyTemplateConfigProvider.class);
        if(p != null) {
            providers.add(p);
        }
        
        p = all.get(JellyTemplateConfig.JellyTemplateConfigProvider.class);
        if(p != null) {
            providers.add(p);
        }
        return providers;
    }
    
    @JavaScriptMethod
    public String[] renderTemplate(String templateFile, String buildId) {
        String[] result = new String[2];
        result[0] = StringUtils.EMPTY;
        result[1] = StringUtils.EMPTY;
        
        try {
            AbstractBuild<?,?> build = project.getBuild(buildId);
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            StreamTaskListener listener = new StreamTaskListener(stream);
            
            if(templateFile.endsWith(".jelly")) {
                JellyScriptContent jellyContent = new JellyScriptContent();
                jellyContent.template = templateFile;                
                result[0] = jellyContent.evaluate(build, listener, "JELLY_SCRIPT");
            } else {
                ScriptContent scriptContent = new ScriptContent();
                scriptContent.template = templateFile;                
                result[0] = scriptContent.evaluate(build, listener, "SCRIPT");                
            }
            result[1] = stream.toString(ExtendedEmailPublisher.descriptor().getCharset());
        } catch (Exception ex) {
            result[0] = renderError(ex);
        }         
        return result;
    }
    
    public AbstractProject<?, ?> getProject() {
        return project;
    }
}
