/*
 * 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 java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import jetbrains.buildServer.ExtensionHolder;
import jetbrains.buildServer.parameters.*;
import jetbrains.buildServer.parameters.impl.*;
import jetbrains.buildServer.serverSide.ParametersPreprocessor;
import jetbrains.buildServer.serverSide.SBuildServer;
import jetbrains.buildServer.serverSide.SRunningBuild;
import org.jetbrains.annotations.NotNull;

/**
 * @author Yegor.Yarko
 *         Date: 04.12.10
 */
public class ScriptedPropertiesParametersPreprocessor implements ParametersPreprocessor {
  private ExtensionHolder myExtensionHolder;
  private SBuildServer myServer;

  public ScriptedPropertiesParametersPreprocessor(ExtensionHolder extensionHolder, SBuildServer server) {
    myExtensionHolder = extensionHolder;
    myServer = server;
  }

  public void fixRunBuildParameters(@NotNull final SRunningBuild build,
                                    @NotNull final Map<String, String> runParameters,
                                    @NotNull final Map<String, String> buildParams) {
    ParametersInOutList params = new ParametersInOutList();
    final ParametersProviderFactory factory =new ParametersProviderFactory() {
      @NotNull
      public MapParametersProvider getParametersProvider() {
        return new MapParametersProviderImpl();
      }
    };
    final ParametersInOut runParametersInOut = new ParametersInOut("runParams", new MapParametersProviderImpl(runParameters), factory);
    params.addParameters(runParametersInOut);

    final ParametersInOut buildParametersInOut = new ParametersInOut("buildParams", new MapParametersProviderImpl(buildParams), factory);
    params.addParameters(buildParametersInOut);

    params.resolveParameters(getParametersResolver(build));

    runParameters.putAll(runParametersInOut.getAllParameters().getAll());
    buildParams.putAll(buildParametersInOut.getAllParameters().getAll());
  }

  private ParameterResolver getParametersResolver(@NotNull final SRunningBuild build) {
    final Collection<ScriptedPropertyProcessor> processors = myExtensionHolder.getExtensions(ScriptedPropertyProcessor.class);
    final ScriptedPropertyRegistry registry = new ScriptedPropertyRegistry(processors);

    final ContextVariables contextVariables = getContextVariables(build);

    return new ParameterResolver() {
      @NotNull
      public ProcessingResult resolve(@NotNull final String key,
                                      @NotNull final String value,
                                      @NotNull final ParametersProvider parameters) {
        return registry.resolve(key, value, parameters, contextVariables, false);
      }
    };
  }

  private ContextVariables getContextVariables(final SRunningBuild build) {
    final HashMap<String, Object> variablesMap = new HashMap<String, Object>();
    //todo: use constants, reuse code from the build
    variablesMap.put("server", myServer);
    variablesMap.put("serverBuild", build);
    return new MapContextVariablesImpl(variablesMap);
  }
}
