/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.samza.util;

import java.util.HashMap;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import org.apache.samza.SamzaException;
import org.apache.samza.config.Config;
import org.apache.samza.config.ConfigException;
import org.apache.samza.config.ConfigRewriter;
import org.apache.samza.config.JobConfig;
import org.apache.samza.config.MapConfig;
import org.apache.samza.config.loaders.PropertiesConfigLoaderFactory;
import org.junit.Test;

import static org.junit.Assert.assertEquals;


public class TestConfigUtil {
  private static final String CONFIG_KEY = "config.key";
  private static final String CONFIG_VALUE = "value";
  private static final String NEW_CONFIG_KEY = "new.rewritten.config.key";
  private static final String REWRITER_NAME = "propertyRewriter";
  private static final String OTHER_REWRITER_NAME = "otherPropertyRewriter";

  @Test
  public void testRewriteConfig() {
    Map<String, String> baseConfigMap = ImmutableMap.of(CONFIG_KEY, CONFIG_VALUE);

    // no rewriters
    Map<String, String> fullConfig = new HashMap<>(baseConfigMap);
    assertEquals(fullConfig, ConfigUtil.rewriteConfig(new MapConfig(fullConfig)));

    // rewriter that adds property
    fullConfig = new HashMap<>(baseConfigMap);
    fullConfig.put(JobConfig.CONFIG_REWRITERS, REWRITER_NAME);
    fullConfig.put(String.format(JobConfig.CONFIG_REWRITER_CLASS, REWRITER_NAME), NewPropertyRewriter.class.getName());
    Map<String, String> expectedConfigMap = new HashMap<>(fullConfig);
    expectedConfigMap.put(NEW_CONFIG_KEY, CONFIG_VALUE);
    assertEquals(new MapConfig(expectedConfigMap), ConfigUtil.rewriteConfig(new MapConfig(fullConfig)));

    // rewriter that updates property
    fullConfig = new HashMap<>(baseConfigMap);
    fullConfig.put(JobConfig.CONFIG_REWRITERS, REWRITER_NAME);
    fullConfig.put(String.format(JobConfig.CONFIG_REWRITER_CLASS, REWRITER_NAME),
        UpdatePropertyRewriter.class.getName());
    expectedConfigMap = new HashMap<>(fullConfig);
    expectedConfigMap.put(CONFIG_KEY, CONFIG_VALUE + CONFIG_VALUE);
    assertEquals(new MapConfig(expectedConfigMap), ConfigUtil.rewriteConfig(new MapConfig(fullConfig)));

    // rewriter that removes property
    fullConfig = new HashMap<>(baseConfigMap);
    fullConfig.put(JobConfig.CONFIG_REWRITERS, REWRITER_NAME);
    fullConfig.put(String.format(JobConfig.CONFIG_REWRITER_CLASS, REWRITER_NAME),
        DeletePropertyRewriter.class.getName());
    expectedConfigMap = new HashMap<>(fullConfig);
    expectedConfigMap.remove(CONFIG_KEY);
    assertEquals(new MapConfig(expectedConfigMap), ConfigUtil.rewriteConfig(new MapConfig(fullConfig)));

    // only apply rewriters from rewriters list
    fullConfig = new HashMap<>(baseConfigMap);
    fullConfig.put(JobConfig.CONFIG_REWRITERS, OTHER_REWRITER_NAME);
    fullConfig.put(String.format(JobConfig.CONFIG_REWRITER_CLASS, REWRITER_NAME), NewPropertyRewriter.class.getName());
    fullConfig.put(String.format(JobConfig.CONFIG_REWRITER_CLASS, OTHER_REWRITER_NAME),
        UpdatePropertyRewriter.class.getName());
    expectedConfigMap = new HashMap<>(fullConfig);
    expectedConfigMap.put(CONFIG_KEY, CONFIG_VALUE + CONFIG_VALUE);
    assertEquals(new MapConfig(expectedConfigMap), ConfigUtil.rewriteConfig(new MapConfig(fullConfig)));

    // two rewriters; second rewriter overwrites configs from first
    fullConfig = new HashMap<>(baseConfigMap);
    fullConfig.put(JobConfig.CONFIG_REWRITERS, REWRITER_NAME + "," + OTHER_REWRITER_NAME);
    fullConfig.put(String.format(JobConfig.CONFIG_REWRITER_CLASS, REWRITER_NAME), NewPropertyRewriter.class.getName());
    fullConfig.put(String.format(JobConfig.CONFIG_REWRITER_CLASS, OTHER_REWRITER_NAME),
        UpdatePropertyRewriter.class.getName());
    expectedConfigMap = new HashMap<>(fullConfig);
    expectedConfigMap.put(NEW_CONFIG_KEY, CONFIG_VALUE + CONFIG_VALUE);
    assertEquals(new MapConfig(expectedConfigMap), ConfigUtil.rewriteConfig(new MapConfig(fullConfig)));
  }

  /**
   * This fails because Util will interpret the empty string value as a single rewriter which has the empty string as a
   * name, and there is no rewriter class config for a rewriter name which is the empty string.
   * TODO: should this be fixed to interpret the empty string as an empty list?
   */
  @Test(expected = SamzaException.class)
  public void testRewriteConfigConfigRewritersEmptyString() {
    Config config = new MapConfig(ImmutableMap.of(JobConfig.CONFIG_REWRITERS, ""));
    ConfigUtil.rewriteConfig(config);
  }

  @Test(expected = SamzaException.class)
  public void testRewriteConfigNoClassForConfigRewriterName() {
    Config config =
        new MapConfig(ImmutableMap.of(CONFIG_KEY, CONFIG_VALUE, JobConfig.CONFIG_REWRITERS, "unknownRewriter"));
    ConfigUtil.rewriteConfig(config);
  }

  @Test(expected = SamzaException.class)
  public void testRewriteConfigRewriterClassDoesNotExist() {
    Config config = new MapConfig(ImmutableMap.of(CONFIG_KEY, CONFIG_VALUE, JobConfig.CONFIG_REWRITERS, REWRITER_NAME,
        String.format(JobConfig.CONFIG_REWRITER_CLASS, REWRITER_NAME), "not_a_class"));
    ConfigUtil.rewriteConfig(config);
  }

  @Test
  public void testApplyRewriter() {
    // new property
    Map<String, String> fullConfig =
        ImmutableMap.of(CONFIG_KEY, CONFIG_VALUE, String.format(JobConfig.CONFIG_REWRITER_CLASS, REWRITER_NAME),
            NewPropertyRewriter.class.getName());
    Map<String, String> expectedConfigMap = new HashMap<>(fullConfig);
    expectedConfigMap.put(NEW_CONFIG_KEY, CONFIG_VALUE);
    assertEquals(new MapConfig(expectedConfigMap), ConfigUtil.applyRewriter(new MapConfig(fullConfig), REWRITER_NAME));

    // update property
    fullConfig =
        ImmutableMap.of(CONFIG_KEY, CONFIG_VALUE, String.format(JobConfig.CONFIG_REWRITER_CLASS, REWRITER_NAME),
            UpdatePropertyRewriter.class.getName());
    expectedConfigMap = new HashMap<>(fullConfig);
    expectedConfigMap.put(CONFIG_KEY, CONFIG_VALUE + CONFIG_VALUE);
    assertEquals(new MapConfig(expectedConfigMap), ConfigUtil.applyRewriter(new MapConfig(fullConfig), REWRITER_NAME));

    // remove property
    fullConfig =
        ImmutableMap.of(CONFIG_KEY, CONFIG_VALUE, String.format(JobConfig.CONFIG_REWRITER_CLASS, REWRITER_NAME),
            DeletePropertyRewriter.class.getName());
    expectedConfigMap = new HashMap<>(fullConfig);
    expectedConfigMap.remove(CONFIG_KEY);
    assertEquals(new MapConfig(expectedConfigMap), ConfigUtil.applyRewriter(new MapConfig(fullConfig), REWRITER_NAME));
  }

  @Test(expected = SamzaException.class)
  public void testApplyRewriterNoClassForConfigRewriterName() {
    Map<String, String> fullConfig = ImmutableMap.of(CONFIG_KEY, CONFIG_VALUE);
    ConfigUtil.applyRewriter(new MapConfig(fullConfig), REWRITER_NAME);
  }

  @Test(expected = SamzaException.class)
  public void testApplyRewriterClassDoesNotExist() {
    Map<String, String> fullConfig =
        ImmutableMap.of(CONFIG_KEY, CONFIG_VALUE, String.format(JobConfig.CONFIG_REWRITER_CLASS, REWRITER_NAME),
            "not_a_class");
    Config expectedConfig = new MapConfig(ImmutableMap.of(CONFIG_KEY, CONFIG_VALUE, NEW_CONFIG_KEY, CONFIG_VALUE));
    assertEquals(expectedConfig, ConfigUtil.applyRewriter(new MapConfig(fullConfig), REWRITER_NAME));
  }

  @Test(expected = ConfigException.class)
  public void testLoadConfigWithoutLoader() {
    Map<String, String> config = new HashMap<>();
    config.put(JobConfig.JOB_NAME, "new-test-job");

    ConfigUtil.loadConfig(new MapConfig(config));
  }

  @Test
  public void testLoadConfigWithOverridesAndRewrites() {
    Map<String, String> config = new HashMap<>();
    config.put(JobConfig.CONFIG_LOADER_FACTORY, PropertiesConfigLoaderFactory.class.getCanonicalName());
    config.put(JobConfig.JOB_NAME, "new-test-job");
    config.put(JobConfig.CONFIG_REWRITERS, REWRITER_NAME);
    config.put(CONFIG_KEY, CONFIG_VALUE);
    config.put(String.format(JobConfig.CONFIG_REWRITER_CLASS, REWRITER_NAME), NewPropertyRewriter.class.getName());
    config.put(PropertiesConfigLoaderFactory.CONFIG_LOADER_PROPERTIES_PREFIX + "path", getClass().getResource("/test.properties").getPath());

    Config actual = ConfigUtil.loadConfig(new MapConfig(config));

    assertEquals("org.apache.samza.job.MockJobFactory", actual.get("job.factory.class"));
    assertEquals("bar", actual.get("foo"));
    // overridden value
    assertEquals("new-test-job", actual.get("job.name"));
    // rewritten value
    assertEquals(CONFIG_VALUE, actual.get(NEW_CONFIG_KEY));
  }

  /**
   * Adds a new config entry for the key {@link #NEW_CONFIG_KEY} which has the same value as {@link #CONFIG_KEY}.
   */
  public static class NewPropertyRewriter implements ConfigRewriter {
    @Override
    public Config rewrite(String name, Config config) {
      ImmutableMap.Builder<String, String> newConfigMapBuilder = new ImmutableMap.Builder<>();
      newConfigMapBuilder.putAll(config);
      newConfigMapBuilder.put(NEW_CONFIG_KEY, config.get(CONFIG_KEY));
      return new MapConfig(newConfigMapBuilder.build());
    }
  }

  /**
   * If an entry at {@link #NEW_CONFIG_KEY} exists, overwrites it to be the value concatenated with itself. Otherwise,
   * updates the entry at {@link #CONFIG_KEY} to be the value concatenated to itself.
   */
  public static class UpdatePropertyRewriter implements ConfigRewriter {
    @Override
    public Config rewrite(String name, Config config) {
      Map<String, String> newConfigMap = new HashMap<>(config);
      if (config.containsKey(NEW_CONFIG_KEY)) {
        // for testing overwriting of new configs
        newConfigMap.put(NEW_CONFIG_KEY, config.get(NEW_CONFIG_KEY) + config.get(NEW_CONFIG_KEY));
      } else {
        newConfigMap.put(CONFIG_KEY, config.get(CONFIG_KEY) + config.get(CONFIG_KEY));
      }
      return new MapConfig(newConfigMap);
    }
  }

  /**
   * Removes config entry for the key {@link #CONFIG_KEY} and {@link #NEW_CONFIG_KEY}.
   */
  public static class DeletePropertyRewriter implements ConfigRewriter {
    @Override
    public Config rewrite(String name, Config config) {
      Map<String, String> newConfigMap = new HashMap<>(config);
      newConfigMap.remove(CONFIG_KEY);
      return new MapConfig(newConfigMap);
    }
  }
}
