/*
 * 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;

import static org.apache.geode.distributed.ConfigurationProperties.MEMBERSHIP_PORT_RANGE;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_SHIRO_INIT;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.TreeSet;

import org.apache.geode.InternalGemFireException;
import org.apache.geode.distributed.internal.FlowControlParams;
import org.apache.geode.internal.net.SocketCreator;
import org.apache.geode.internal.security.SecurableCommunicationChannel;
import org.apache.geode.internal.util.ArgumentRedactor;

/**
 * Provides an implementation of the {@link Config} interface that implements functionality that all
 * {@link Config} implementations can share.
 */
public abstract class AbstractConfig implements Config {

  private static final String GEM_FIRE_PROPERTIES_USING_DEFAULT_VALUES =
      "### GemFire Properties using default values ###";
  private static final String GEM_FIRE_PROPERTIES_DEFINED_WITH_PREFIX =
      "### GemFire Properties defined with ";
  private static final String GEM_FIRE_PROPERTIES_DEFINED_WITH_SUFFIX = " ###";

  /**
   * Use {@link #toLoggerString()} instead. If you need to override this in a subclass, be careful
   * not to expose any private data or security related values. Fixing bug #48155 by not exposing
   * all values.
   */
  @Override
  public String toString() {
    return super.toString();
  }

  @Override
  public String toLoggerString() {
    StringWriter stringWriter = new StringWriter();
    PrintWriter printWriter = new PrintWriter(stringWriter);
    printSourceSection(ConfigSource.runtime(), printWriter);
    printSourceSection(ConfigSource.sysprop(), printWriter);
    printSourceSection(ConfigSource.api(), printWriter);
    for (ConfigSource fileSource : getFileSources()) {
      printSourceSection(fileSource, printWriter);
    }
    printSourceSection(ConfigSource.xml(), printWriter);
    printSourceSection(ConfigSource.launcher(), printWriter); // fix for bug 46653
    printSourceSection(null, printWriter);
    printWriter.close();
    return stringWriter.toString();
  }

  /**
   * Gets the Map of GemFire properties and values from a given ConfigSource
   *
   * @return map of GemFire properties and values
   */
  public Map<String, String> getConfigPropsFromSource(ConfigSource source) {
    Map<String, String> configProps = new HashMap<>();
    String[] validAttributeNames = getAttributeNames();
    Map<String, ConfigSource> sm = getAttSourceMap();

    for (String name : validAttributeNames) {
      if (source == null && sm.get(name) != null
          || source != null && !source.equals(sm.get(name))) {
        continue;
      }
      configProps.put(name, getAttribute(name));
    }
    return configProps;
  }

  /**
   * Gets all the GemFire properties defined using file(s)
   *
   * @return Map of GemFire properties and values set using property files
   */
  public Map<String, String> getConfigPropsDefinedUsingFiles() {
    Map<String, String> configProps = new HashMap<>();
    for (ConfigSource fileSource : getFileSources()) {
      configProps.putAll(getConfigPropsFromSource(fileSource));
    }
    return configProps;
  }

  @Override
  public Properties toProperties() {
    Properties result = new SortedProperties();
    String[] attNames = getAttributeNames();
    for (String name : attNames) {
      result.setProperty(name, getAttribute(name));
    }
    return result;
  }

  @Override
  public void toFile(File file) throws IOException {
    try (FileOutputStream out = new FileOutputStream(file)) {
      toProperties().store(out, null);
    }
  }

  @Override
  public boolean sameAs(Config other) {
    if (this == other) {
      return true;
    }
    if (other == null) {
      return false;
    }
    if (!getClass().equals(other.getClass())) {
      return false;
    }
    String[] validAttributeNames = getAttributeNames();
    for (String name : validAttributeNames) {
      Object thisAtt = getAttributeObject(name);
      Object otherAtt = other.getAttributeObject(name);
      if (thisAtt != otherAtt) {
        if (thisAtt == null) {
          return false;
        } else if (thisAtt.getClass().isArray()) {
          int thisLength = Array.getLength(thisAtt);
          int otherLength = Array.getLength(otherAtt);
          if (thisLength != otherLength) {
            return false;
          }
          for (int j = 0; j < thisLength; j++) {
            Object thisArrObj = Array.get(thisAtt, j);
            Object otherArrObj = Array.get(otherAtt, j);
            if (thisArrObj != otherArrObj) {
              if (thisArrObj == null) {
                return false;
              } else if (!thisArrObj.equals(otherArrObj)) {
                return false;
              }
            }
          }
        } else if (!thisAtt.equals(otherAtt)) {
          return false;
        }
      }
    }
    return true;
  }

  @Override
  public String getAttribute(String name) {
    Object result = getAttributeObject(name);
    if (result instanceof String) {
      return (String) result;
    }

    if (name.equalsIgnoreCase(MEMBERSHIP_PORT_RANGE)) {
      int[] value = (int[]) result;
      return "" + value[0] + "-" + value[1];
    }

    if (result.getClass().isArray() && name.startsWith("ssl-")) {
      return SystemAdmin.join((Object[]) result, ",");
    }

    if (result.getClass().isArray()) {
      return SystemAdmin.join((Object[]) result);
    }

    if (result instanceof InetAddress) {
      InetAddress addr = (InetAddress) result;
      String addrName;
      if (addr.isMulticastAddress() || !SocketCreator.resolve_dns) {
        // on Windows getHostName on mcast addrs takes ~5 seconds
        addrName = addr.getHostAddress();
      } else {
        addrName = SocketCreator.getHostName(addr);
      }
      return addrName;
    }

    return result.toString();
  }

  @Override
  public ConfigSource getAttributeSource(String name) {
    return getAttSourceMap().get(name);
  }

  @Override
  public void setAttribute(String name, String value, ConfigSource source) {
    Object attObjectValue;
    Class valueType = getAttributeType(name);
    try {
      if (valueType.equals(String.class)) {
        attObjectValue = value;
      } else if (valueType.equals(String[].class)) {
        attObjectValue = value.split(",");
      } else if (valueType.equals(Integer.class)) {
        attObjectValue = Integer.valueOf(value);
      } else if (valueType.equals(Long.class)) {
        attObjectValue = Long.valueOf(value);
      } else if (valueType.equals(Boolean.class)) {
        attObjectValue = Boolean.valueOf(value);
      } else if (valueType.equals(File.class)) {
        attObjectValue = new File(value);
      } else if (valueType.equals(int[].class)) {
        int minus = value.indexOf('-');
        if (minus <= 0) {
          throw new IllegalArgumentException(
              "expected a setting in the form X-Y but found no dash for attribute " + name);
        }
        int[] tempValue = new int[2];
        tempValue[0] = Integer.valueOf(value.substring(0, minus));
        tempValue[1] = Integer.valueOf(value.substring(minus + 1));
        attObjectValue = tempValue;
      } else if (valueType.equals(InetAddress.class)) {
        try {
          attObjectValue = InetAddress.getByName(value);
        } catch (UnknownHostException ex) {
          throw new IllegalArgumentException(
              String.format("%s value %s must be a valid host name. %s",
                  name, value, ex.toString()));
        }
      } else if (valueType.equals(FlowControlParams.class)) {
        String[] values = value.split(",");
        if (values.length != 3) {
          throw new IllegalArgumentException(
              String.format("%s value %s must have three elements separated by commas",
                  name, value));
        }
        int allowance;
        float threshold;
        int waitTime;
        try {
          allowance = Integer.parseInt(values[0].trim());
          threshold = Float.valueOf(values[1].trim());
          waitTime = Integer.parseInt(values[2].trim());
        } catch (NumberFormatException e) {
          throw new IllegalArgumentException(
              String.format("%s value %s must be composed of an integer, a float, and an integer",
                  name, value));
        }
        attObjectValue = new FlowControlParams(allowance, threshold, waitTime);
      } else if (valueType.isArray()
          && SecurableCommunicationChannel.class.equals(valueType.getComponentType())) {
        attObjectValue = commaDelimitedStringToSecurableCommunicationChannels(value);
      } else {
        throw new InternalGemFireException(
            String.format("unhandled attribute type %s for %s.",
                valueType, name));
      }
    } catch (NumberFormatException ex) {
      throw new IllegalArgumentException(String.format("%s value %s must be a number.",
          name, value));
    }

    setAttributeObject(name, attObjectValue, source);
  }

  @Override
  public String getAttributeDescription(String name) {
    checkAttributeName(name);
    if (!getAttDescMap().containsKey(name)) {
      throw new InternalGemFireException(
          String.format("unhandled attribute name %s.", name));
    }
    return (String) getAttDescMap().get(name);
  }

  /**
   * Returns the string to use as the exception message when an attempt is made to set an
   * unmodifiable attribute.
   */
  protected String _getUnmodifiableMsg(String name) {
    return String.format("The %s configuration attribute can not be modified.",
        name);
  }

  /**
   * Returns a map that contains attribute descriptions
   */
  protected abstract Map getAttDescMap();

  protected abstract Map<String, ConfigSource> getAttSourceMap();

  /**
   * Set to true if most of the attributes can be modified. Set to false if most of the attributes
   * are read only.
   */
  protected boolean _modifiableDefault() {
    return false;
  }

  protected void checkAttributeName(String name) {
    String[] validAttNames = getAttributeNames();
    if (!Arrays.asList(validAttNames).contains(name.toLowerCase())) {
      throw new IllegalArgumentException(
          String.format("Unknown configuration attribute name %s. Valid attribute names are: %s .",
              name, SystemAdmin.join(validAttNames)));
    }
  }

  private List<ConfigSource> getFileSources() {
    ArrayList<ConfigSource> result = new ArrayList<>();
    for (ConfigSource cs : getAttSourceMap().values()) {
      if (cs.getType() == ConfigSource.Type.FILE || cs.getType() == ConfigSource.Type.SECURE_FILE) {
        if (!result.contains(cs)) {
          result.add(cs);
        }
      }
    }
    return result;
  }

  private void printSourceSection(ConfigSource source, PrintWriter printWriter) {
    String[] validAttributeNames = getAttributeNames();
    boolean sourceFound = false;
    Map<String, ConfigSource> sourceMap = getAttSourceMap();
    boolean sourceIsSecured = false;
    if (source != null && source.getType() == ConfigSource.Type.SECURE_FILE) {
      sourceIsSecured = true;
    }
    for (String name : validAttributeNames) {
      if (source == null) {
        if (sourceMap.get(name) != null) {
          continue;
        }
      } else if (!source.equals(sourceMap.get(name))) {
        continue;
      }
      if (!sourceFound) {
        sourceFound = true;
        if (source == null) {
          printWriter.println(GEM_FIRE_PROPERTIES_USING_DEFAULT_VALUES);
        } else {
          printWriter.println(GEM_FIRE_PROPERTIES_DEFINED_WITH_PREFIX + source.getDescription()
              + GEM_FIRE_PROPERTIES_DEFINED_WITH_SUFFIX);
        }
      }
      // hide the shiro-init configuration for now. Remove after we can allow customer to specify
      // shiro.ini file
      if (name.equals(SECURITY_SHIRO_INIT)) {
        continue;
      }

      String attributeValueToPrint;
      if (source == null) {
        // always show defaults values
        attributeValueToPrint = getAttribute(name);
      } else if (sourceIsSecured) {
        // Never show secure sources
        attributeValueToPrint = ArgumentRedactor.redacted;
      } else {
        // Otherwise, redact based on the key string
        attributeValueToPrint =
            ArgumentRedactor.redactArgumentIfNecessary(name, getAttribute(name));
      }
      printWriter.print(name);
      printWriter.print('=');
      printWriter.println(attributeValueToPrint);
    }
  }

  private SecurableCommunicationChannel[] commaDelimitedStringToSecurableCommunicationChannels(
      final String tokenizeString) {
    StringTokenizer stringTokenizer = new StringTokenizer(tokenizeString, ",");
    SecurableCommunicationChannel[] returnArray =
        new SecurableCommunicationChannel[stringTokenizer.countTokens()];
    for (int i = 0; i < returnArray.length; i++) {
      String name = stringTokenizer.nextToken();
      try {
        returnArray[i] = SecurableCommunicationChannel.getEnum(name);
      } catch (Exception e) {
        throw new IllegalArgumentException(e);
      }
    }
    return returnArray;
  }

  /**
   * This class was added to fix bug 39382. It does this be overriding "keys" which is used by the
   * store0 implementation of Properties.
   */
  protected static class SortedProperties extends Properties {

    private static final long serialVersionUID = 7156507110684631135L;

    @Override
    public Enumeration keys() {
      // the TreeSet gets the sorting we desire but is only safe
      // because the keys in this context are always String which is Comparable
      return Collections.enumeration(new TreeSet(keySet()));
    }
  }
}
