/*
 * 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.parameters.ContextVariables;
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.ProcessingResultImpl;
import junit.framework.TestCase;
import org.jetbrains.annotations.NotNull;

/**
 * Created by IntelliJ IDEA.
 * User: yaegor
 * Date: 18.09.2010
 * Time: 13:27:04
 * To change this template use File | Settings | File Templates.
 */
public class ScriptingPropertyParsingTest extends TestCase {

  public void testNoParamTextParsing() {
    ScriptedPropertyRegistry registry = new ScriptedPropertyRegistry();
    registry.registerScriptedPropertyType(new EmptyScriptedPropertyProcessor("a") {
      @Override
      public ProcessingResult process(@NotNull ParametersProvider parameters, @NotNull ContextVariables contextVariables) {
        return new ProcessingResultImpl("b", true, true);
      }
    });
    checkResult(registry, "##a", "b", true, true);
    checkResult(registry, "#a", "#a", false, true);
    checkResult(registry, "##a##a", "bb", true, true);
    checkResult(registry, "##a###a", "b#b", true, true);
    checkResult(registry, "##a(###a", "b(#b", true, true);
    checkResult(registry, "c##a", "cb", true, true);
    checkResult(registry, "##b", "##b", false, true);
    checkResult(registry, "###", "###", false, true);
  }

  public void testSimpleParamTextParsing() {
    ScriptedPropertyRegistry registry = new ScriptedPropertyRegistry();
    registry.registerScriptedPropertyType(new EmptyScriptedPropertyProcessor("2upper") {
      @Override
      public ProcessingResult process(@NotNull String value,
                                      @NotNull ParametersProvider parameters,
                                      @NotNull ContextVariables contextVariables) {
        return new ProcessingResultImpl(value.toUpperCase(), true, true);
      }
    });
    checkResult(registry, "##2upper::xxx", "XXX", true, true);
    checkResult(registry, "##2upper::xxx::", "XXX::", true, true);
    checkResult(registry, "##2upper::xxx##", "XXX##", true, true);
    checkResult(registry, "##2upper:", "##2upper:", false, true);
    checkResult(registry, "##2upper:::", ":", true, true);
    checkResult(registry, "##2upper::", "##2upper::", false, true);
    checkResult(registry, "##2upper::^##2upper::s", "^##2UPPER::S", true, true);

    checkResult(registry, "##2upper::xxx##y", "XXX##Y", true, true);
    checkResult(registry, "##2upper::xxx:y", "XXX:Y", true, true);

    checkResult(registry, "##2upper::a b", "A b", true, true);
    checkResult(registry, "##2upper::a\tb", "A\tb", true, true);
    checkResult(registry, "##2upper::cat=>~!@#$%^&*()_+`=;':[]{}\\<>?/.,|mouse nicht", "CAT=>~!@#$%^&*()_+`=;':[]{}\\<>?/.,|MOUSE nicht",
                true, true);
    checkResult(registry, "##2upper::cat=>~!@#$%^&*()_+`=;':[]{}\\< >?/.,|mouse nicht", "CAT=>~!@#$%^&*()_+`=;':[]{}\\< >?/.,|mouse nicht",
                true, true);
    checkResult(registry, "##2upper::a b##2upper::c d", "A bC d", true, true);
  }

  public void testParamTextWithEndSequenceParsing() {
    ScriptedPropertyRegistry registry = new ScriptedPropertyRegistry();
    registry.registerScriptedPropertyType(new EmptyScriptedPropertyProcessor("2upper") {
      @Override
      public ProcessingResult process(@NotNull String value,
                                      @NotNull ParametersProvider parameters,
                                      @NotNull ContextVariables contextVariables) {
        return new ProcessingResultImpl(value.toUpperCase(), true, true);
      }
    });
    checkResult(registry, "##2upper:/:xxx/", "XXX", true, true);
    checkResult(registry, "##2upper:#:xxx#yyy", "XXXyyy", true, true);
    checkResult(registry, "##2upper:1:xxx111", "XXX11", true, true);
    checkResult(registry, "##2upper:1:#\\'\":1", "#\\'\":", true, true);
    checkResult(registry, "##2upper:end:sunnyendaa##2upper:oops:beachoops", "SUNNYaaBEACH", true, true);
    checkResult(registry, "##2upper:/::xyz/", ":XYZ", true, true);
    checkResult(registry, "##2upper:/:several words/", "SEVERAL WORDS", true, true);
    checkResult(registry, "##2upper:}:##2upper::xxx[", "##2upper:}:XXX[", true, true);
  }

  private void checkResult(ScriptedPropertyRegistry registry,
                           String originalValue,
                           String newValue,
                           boolean modified,
                           boolean fullyResolved) {
    final ProcessingResult result =
      registry.resolve("key", originalValue, new MapParametersProviderImpl(), new MapContextVariablesImpl(), false);
    assertEquals("Wrong resolved value", newValue, result.getResult());
    assertEquals("Wrong 'modified' flag", modified, result.isModified());
    assertEquals("Wrong 'fully resolved' flag", fullyResolved, result.isFullyResolved());
  }
}
