/*
 * 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.geode.internal.cache.xmlcache;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.logging.log4j.Logger;

import org.apache.geode.annotations.Immutable;
import org.apache.geode.internal.logging.LogService;

/**
 * Helper class for CacheXmlPropertyResolver. Helps in parsing ${...${}..}..${} strings.
 *
 * @since GemFire 6.6
 */
public class CacheXmlPropertyResolverHelper {
  private static final Logger logger = LogService.getLogger();

  public static final String DEFAULT_PROPERTY_STRING_PREFIX = "${";

  public static final String DEFAULT_PROPERTY_STRING_SUFFIX = "}";

  public static final String DEFAULT_PREFIX_FOR_SUFFIX = "{";
  /**
   * This <code>HashMap </code> contains valid suffixes and prefixes to be parsed by
   * {@link CacheXmlPropertyResolverHelper} like {}, [] or ().
   */
  @Immutable
  private static final Map<String, String> validSuffixAndPrefixes;

  static {
    Map<String, String> map = new HashMap<>();
    map.put("}", "{");
    map.put("]", "[");
    map.put(")", "(");
    validSuffixAndPrefixes = Collections.unmodifiableMap(map);
  }
  /* String specifying the suffice for property key prefix */
  private String propertyPrefix = DEFAULT_PROPERTY_STRING_PREFIX;

  /* String specifying the suffice for property key suffix */
  private String propertySuffix = DEFAULT_PROPERTY_STRING_SUFFIX;

  private String prefixForSuffix = DEFAULT_PREFIX_FOR_SUFFIX;

  public CacheXmlPropertyResolverHelper(String propPrefix, String propSuffix) {
    if (propPrefix != null && propSuffix != null) {
      String validPrefix = validSuffixAndPrefixes.get(propSuffix);
      if (validPrefix != null && propPrefix.endsWith(validPrefix)) {
        this.prefixForSuffix = validPrefix;
      } else {
        this.prefixForSuffix = propPrefix;
      }
      this.propertyPrefix = propPrefix;

      this.propertySuffix = propSuffix;
    }
  }

  /**
   * Parses the given string which are supposed to be like ${} for system and/or Gemfire properties
   * to be replaced. This will return property.name from ${property.name}.
   *
   */
  protected String parseResolvablePropString(String unparsedString, PropertyResolver resolver,
      Set<String> visitedReplaceableStrings) {
    StringBuilder buf = new StringBuilder(unparsedString);
    int prefixIndex = buf.indexOf(propertyPrefix);

    while (prefixIndex != -1) {
      int suffixIndex = findSuffixIndex(buf, prefixIndex + propertyPrefix.length());
      if (suffixIndex != -1) {
        String replaceableString =
            buf.substring(prefixIndex + propertyPrefix.length(), suffixIndex);
        // Check for circular references
        if (!visitedReplaceableStrings.add(replaceableString)) {
          logger.info(
              "Some still unresolved string {} was replaced by resolver, leading to circular references.",
              replaceableString);
          throw new IllegalArgumentException("Some still unresolved string " + replaceableString
              + " was replaced by resolver, leading to circular references.");
        }
        /** Find the replacement using given <code>resolver</code> */
        replaceableString =
            parseResolvablePropString(replaceableString, resolver, visitedReplaceableStrings);
        String replacement = resolver.resolveReplaceString(replaceableString);

        if (replacement != null) {
          /**
           * put replacement in <code>unparsedString</code> and call
           * <code>parseResolvablePropString</code> recursively to find more unparsedStrings in the
           * replaced value of given unparsedString.
           */
          replacement = parseResolvablePropString(replacement, resolver, visitedReplaceableStrings);
          buf.replace(prefixIndex, suffixIndex + propertySuffix.length(), replacement);
          prefixIndex = buf.indexOf(propertyPrefix, prefixIndex + replacement.length());
        } else if (resolver.isIgnoreUnresolvedProperties()) {
          /** Look for more replaceable strings in given <code>unparsedString</code>. */
          prefixIndex = buf.indexOf(propertyPrefix, suffixIndex + propertySuffix.length());
        } else {
          throw new IllegalArgumentException(
              "No replacement found for property : " + replaceableString);
        }
        // Before iterating again remove replaceable string from visitedReplaceableStrings as it can
        // appear again.
        visitedReplaceableStrings.remove(replaceableString);
      } else {
        prefixIndex = -1;
      }
    }

    return buf.toString();
  }

  /**
   * Finds index of suffix in a string from a specified index. Like finds index of "}" in string
   * "${my.prop.name}" starting from index 2, which is 14.
   *
   */
  private int findSuffixIndex(StringBuilder buf, int index) {
    int inNestedProperty = 0;
    while (index < buf.length()) {
      if (buf.substring(index, index + this.propertySuffix.length())
          .equalsIgnoreCase(this.propertySuffix)) {
        if (inNestedProperty > 0) {
          inNestedProperty--;
          index = index + this.propertySuffix.length();
        } else {
          return index;
        }
      } else if (buf.substring(index, index + this.prefixForSuffix.length())
          .equalsIgnoreCase(this.prefixForSuffix)) {
        inNestedProperty++;
        index = index + this.prefixForSuffix.length();
      } else {
        index++;
      }
    }
    return -1;
  }
}
