/*
 * Copyright 2000-2010 JetBrains s.r.o.
 *
 * 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 jetbrains.buildServer.scriptedProperties;

import jetbrains.buildServer.DefaultExtensionAccessor;
import jetbrains.buildServer.ExtendableServiceLocator;
import jetbrains.buildServer.ExtensionAccessor;
import jetbrains.buildServer.agent.BuildAgentConfiguration;
import jetbrains.buildServer.agent.impl.parameters.factory.ResolverFromExtensionsFactory;
import jetbrains.buildServer.agent.impl.parameters.resolve.ReferenceResolverAgentProvider;
import jetbrains.buildServer.agent.parameters.ParameterResolverAgentProvider;
import jetbrains.buildServer.parameters.ContextVariables;
import jetbrains.buildServer.parameters.ParameterResolver;
import jetbrains.buildServer.parameters.ParametersProvider;
import jetbrains.buildServer.parameters.ProcessingResult;
import jetbrains.buildServer.parameters.impl.MapContextVariablesImpl;
import jetbrains.buildServer.parameters.impl.MapParametersProviderImpl;
import jetbrains.buildServer.parameters.impl.ParametersResolverUtil;
import jetbrains.buildServer.parameters.impl.ProcessingResultImpl;
import junit.framework.TestCase;
import org.jetbrains.annotations.NotNull;

/**
 * @author Yegor.Yarko
 *         Date: 30.10.10
 */
public class ScriptingPropertyWithReferenceResolverTest extends TestCase {
  ResolverFromExtensionsFactory myFactory;

  protected void setUp() {
    final ExtendableServiceLocator extensionHolder = new ExtendableServiceLocator();
    final ExtensionAccessor extensionAccessor = new DefaultExtensionAccessor();
    extensionHolder.setAccessor(extensionAccessor);

    extensionAccessor.registerExtension(ParameterResolverAgentProvider.class, "sourceId1", new ReferenceResolverAgentProvider());
    extensionAccessor.registerExtension(ParameterResolverAgentProvider.class, "sourceId2",
                                        new ScriptedPropertiesAgentParameterResolverProvider(extensionHolder, null));
    extensionAccessor.registerExtension(ScriptedPropertyProcessor.class, "sourceId3", new EmptyScriptedPropertyProcessor("aa") {
      @Override
      public ProcessingResult process(@NotNull final ParametersProvider parameters, @NotNull final ContextVariables contextVariables) {
        return new ProcessingResultImpl("b", true, true);
      }
    });

    myFactory = new ResolverFromExtensionsFactory(extensionHolder);
  }

  public void testReferencesAreSetup() {
    final MapParametersProviderImpl parameters = new MapParametersProviderImpl();
    parameters.put("p1", "v1");

    checkResult(myFactory, parameters, "%p1%", "v1", true, true);
  }

  public void testScriptedAreSetup() {
    final MapParametersProviderImpl parameters = new MapParametersProviderImpl();
    checkResult(myFactory, parameters, "##aa", "b", true, true);
  }

  public void testScriptedInsideReference() {

    final MapParametersProviderImpl parameters = new MapParametersProviderImpl();
    parameters.put("p1", "##aa");
    parameters.put("p2", "v2");
    parameters.put("p3", "%p1%");

    checkResult(myFactory, parameters, "%p3%", "b", true, true);
  }

  public void testReferenceInsideScripted() {

    final MapParametersProviderImpl parameters = new MapParametersProviderImpl();
    parameters.put("p1", "##a%p2%");
    parameters.put("p2", "a");
    parameters.put("p3", "%p1%");

    checkResult(myFactory, parameters, "%p3%", "b", true, true);
  }

  public void testReferenceNearScripted() {

    final MapParametersProviderImpl parameters = new MapParametersProviderImpl();
    parameters.put("p1", "%p4%##a%p2%%p4%");
    parameters.put("p2", "a");
    parameters.put("p3", "%p1%");
    parameters.put("p4", "^");

    checkResult(myFactory, parameters, "%p3%", "^b^", true, true);
  }

  private static void checkResult(final ResolverFromExtensionsFactory factory,
                                  final MapParametersProviderImpl parameters,
                                  String originalValue,
                                  String newValue,
                                  boolean modified,
                                  boolean fullyResolved) {
    final MapContextVariablesImpl variables = new MapContextVariablesImpl();
    final ParameterResolver parameterResolver = factory.createParameterResolver(variables);

    final ProcessingResult result = ParametersResolverUtil.resolveSingleValue(originalValue, parameters, parameterResolver);

    assertEquals("Wrong resolved value", newValue, result.getResult());
    assertEquals("Wrong 'modified' flag", modified, result.isModified());
    assertEquals("Wrong 'fully resolved' flag", fullyResolved, result.isFullyResolved());
  }
}
