/*
 * Copyright 2013 Oleg Nenashev <nenashev@synopsys.com>, Synopsys Inc.
 *
 * Licensed 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 com.synopsys.arc.jenkinsci.plugins.extratoolinstallers.utils;

import hudson.EnvVars;
import hudson.model.Hudson;
import hudson.model.Node;
import hudson.slaves.EnvironmentVariablesNodeProperty;
import hudson.slaves.NodeProperty;
import hudson.tools.ToolInstaller;
import jenkins.model.Jenkins;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
 * Provides parsing of environment variables in input string.
 * @author Oleg Nenashev
 * @since 0.3
 */
public class EnvStringParseHelper {
    private EnvStringParseHelper() {};
    
    /**
     * Resolves tools installation directory using global variables.
     * @param environment Collection of environment variables
     * @param macroString Input path with macro calls
     * @return  Raw string
     * @since 0.3
     */
    public static String substituteEnvVars(String macroString, EnvVars environment)  {
        if (macroString == null) return null;
        if (!macroString.contains("${")) {
            return macroString;
        }    
        return environment.expand(macroString);     
    }

    @Nullable
    public static String substituteNodeVariables(@CheckForNull String macroString, @Nonnull Node node) {
        if (macroString == null) return null;
        if (!macroString.contains("${")) {
            return macroString;
        } 
        
        // Check node properties
        String substitutedString = macroString;
        for (NodeProperty<?> entry : node.getNodeProperties()) {
            substitutedString = substituteNodeProperty(substitutedString, entry);
        }    
        
        // Substitute global variables
        for (NodeProperty<?> entry : Jenkins.getActiveInstance().getGlobalNodeProperties()) {
            substitutedString = substituteNodeProperty(substitutedString, entry);
        } 
        
        return substitutedString;
    }
        
    /**
     * Substitutes string according to node property.
     * @param macroString String to be substituted
     * @param property Node property
     * @return Substituted string
     * @since 0.3
     */
    public static String substituteNodeProperty(String macroString, NodeProperty<?> property) {
        // Get environment variables
        if (property != null && property instanceof EnvironmentVariablesNodeProperty ) {
           EnvironmentVariablesNodeProperty prop = (EnvironmentVariablesNodeProperty)property;
           return substituteEnvVars(macroString, prop.getEnvVars());
        }
        
        //TODO: add support of other configuration entries or propagate environments
        return macroString;
    }
    
    /**
     * Resolves tools installation directory using global variables.
     * @param macroString Input path with macro calls
     * @throws ExtraToolInstallersException String validation failed (there are unresolved variables)
     * @since 0.3
     */
    public static void checkStringForMacro(ToolInstaller installer, String stringName, String macroString) 
            throws ExtraToolInstallersException {     
        // Check consistency and throw errors
        if (macroString.contains("${")) {
           throw new ExtraToolInstallersException(installer, "Can't resolve all variables in "+stringName+" string. Final state: "+macroString);
        } 
    }
}

@@ -728,36 +728,8 @@
 rs;%0A
-import hudson.model.Hudson;%0A
 impo
@@ -1196,20 +1196,16 @@
 r() %7B%7D;%0A
-    
 %0A    /**
@@ -1652,36 +1652,32 @@
 tring;%0A        %7D
-    
 %0A        return 
@@ -1712,20 +1712,248 @@
 ng);
- 
+%0A    %7D%0A%0A
     
+/**
 %0A    
-%7D%0A
+ * Substitutes string according to all node properties.%0A     * @param macroString String to be substituted%0A     * @param node Node whose properties provide available substitution%0A     * @return Substituted string%0A     */
 %0A   
@@ -2194,34 +2194,25 @@
 g;%0A        %7D
- %0A        
+%0A
 %0A        // 
@@ -2437,29 +2437,17 @@
        %7D
-    %0A        
+%0A
 %0A       
@@ -2470,32 +2470,95 @@
 lobal variables%0A
+        final Jenkins jenkinsInstance = Jenkins.getInstance();%0A
         for (Nod
@@ -2582,33 +2582,23 @@
 y : 
-J
+j
 enkins
-.getActive
 Instance
 ().g
@@ -2593,18 +2593,16 @@
 Instance
-()
 .getGlob
@@ -2714,26 +2714,17 @@
        %7D
- %0A        
+%0A
 %0A       
@@ -2752,32 +2752,24 @@
 ring;%0A    %7D%0A
-        
 %0A    /**%0A   
@@ -3363,24 +3363,16 @@
       %7D%0A
-        
 %0A       
@@ -3483,20 +3483,16 @@
 ;%0A    %7D%0A
-    
 %0A    /**
@@ -3503,123 +3503,266 @@
   * 
-Resolves tools installation directory using global variables.%0A     * @param macroString Input path with macro calls
+Checks that all variables have been resolved.%0A     * @param installer The installer that's doing the checking.%0A     * @param stringName The human-friendly name of the string being checked.%0A     * @param macroString The string contents that should be checked.
 %0A   
@@ -3992,17 +3992,16 @@
 oString)
- 
 %0A       
@@ -4042,21 +4042,16 @@
 eption %7B
-     
 %0A       
@@ -4285,17 +4285,16 @@
        %7D
- 
 %0A    %7D%0A%7D

Fix warnings in EnvStringParseHelper