/*
 * 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.distributed.internal;

import static org.apache.geode.distributed.ConfigurationProperties.ACK_WAIT_THRESHOLD;
import static org.apache.geode.distributed.ConfigurationProperties.ARCHIVE_DISK_SPACE_LIMIT;
import static org.apache.geode.distributed.ConfigurationProperties.ARCHIVE_FILE_SIZE_LIMIT;
import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.ENABLE_CLUSTER_CONFIGURATION;
import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_PORT;
import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_SSL_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_HTTP_PORT;
import static org.apache.geode.distributed.ConfigurationProperties.LOG_DISK_SPACE_LIMIT;
import static org.apache.geode.distributed.ConfigurationProperties.LOG_FILE_SIZE_LIMIT;
import static org.apache.geode.distributed.ConfigurationProperties.LOG_LEVEL;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
import static org.apache.geode.distributed.ConfigurationProperties.REDUNDANCY_ZONE;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_LOG_LEVEL;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_MANAGER;
import static org.apache.geode.distributed.ConfigurationProperties.SECURITY_POST_PROCESSOR;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_ENABLED_COMPONENTS;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_ENDPOINT_IDENTIFICATION_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.SSL_USE_DEFAULT_CONTEXT;
import static org.apache.geode.distributed.ConfigurationProperties.START_LOCATOR;
import static org.apache.geode.distributed.ConfigurationProperties.STATISTIC_ARCHIVE_FILE;
import static org.apache.geode.distributed.ConfigurationProperties.STATISTIC_SAMPLE_RATE;
import static org.apache.geode.distributed.ConfigurationProperties.STATISTIC_SAMPLING_ENABLED;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import org.apache.geode.UnmodifiableException;
import org.apache.geode.internal.ConfigSource;
import org.apache.geode.security.TestPostProcessor;
import org.apache.geode.security.TestSecurityManager;
import org.apache.geode.test.junit.categories.MembershipTest;

@Category({MembershipTest.class})
public class DistributionConfigJUnitTest {

  private Map<Class<?>, Class<?>> classMap;

  private Map<String, ConfigAttribute> attributes;
  private Map<String, Method> setters;
  private Map<String, Method> getters;
  private Map<String, Method> checkers;
  private String[] attNames;

  private DistributionConfigImpl config;

  @Before
  public void before() {
    classMap = new HashMap<>();
    classMap.put(boolean.class, Boolean.class);
    classMap.put(byte.class, Byte.class);
    classMap.put(short.class, Short.class);
    classMap.put(char.class, Character.class);
    classMap.put(int.class, Integer.class);
    classMap.put(long.class, Long.class);
    classMap.put(float.class, Float.class);
    classMap.put(double.class, Double.class);

    attributes = DistributionConfig.attributes;
    setters = DistributionConfig.setters;
    getters = DistributionConfig.getters;
    attNames = DistributionConfig.dcValidAttributeNames;
    checkers = AbstractDistributionConfig.checkers;

    config = new DistributionConfigImpl(new Properties());
  }

  @Test
  public void testGetAttributeNames() {
    String[] attNames = AbstractDistributionConfig._getAttNames();
    assertThat(attNames.length).isEqualTo(166);

    List boolList = new ArrayList();
    List intList = new ArrayList();
    List fileList = new ArrayList();
    List stringList = new ArrayList();
    List otherList = new ArrayList();
    for (String attName : attNames) {
      Class clazz = AbstractDistributionConfig._getAttributeType(attName);
      if (clazz.equals(Boolean.class)) {
        boolList.add(attName);
      } else if (clazz.equals(Integer.class)) {
        intList.add(attName);
      } else if (clazz.equals(String.class)) {
        stringList.add(attName);
      } else if (clazz.equals(File.class)) {
        fileList.add(attName);
      } else {
        otherList.add(attName);
      }
    }

    System.out.println("boolList: " + boolList);
    System.out.println();
    System.out.println("intList: " + intList);
    System.out.println();
    System.out.println("stringlList: " + stringList);
    System.out.println();
    System.out.println("filelList: " + fileList);
    System.out.println();
    System.out.println("otherList: " + otherList);

    // TODO - This makes no sense. One has no idea what the correct expected number of attributes
    // are.
    assertEquals(35, boolList.size());
    assertEquals(35, intList.size());
    assertEquals(87, stringList.size());
    assertEquals(5, fileList.size());
    assertEquals(4, otherList.size());
  }

  @Test
  public void testAttributeDesc() {
    String[] attNames = AbstractDistributionConfig._getAttNames();
    for (String attName : attNames) {
      assertTrue("Does not contain description for attribute " + attName,
          AbstractDistributionConfig.dcAttDescriptions.containsKey(attName));
    }
    List<String> attList = Arrays.asList(attNames);
    for (Object attName : AbstractDistributionConfig.dcAttDescriptions.keySet()) {
      if (!attList.contains(attName)) {
        System.out.println("Has unused description for " + attName.toString());
      }
    }
  }

  @Test
  public void sameCount() {
    assertEquals(attributes.size(), setters.size());
    assertEquals(setters.size(), getters.size());
  }

  @Test
  public void everyAttrHasValidSetter() {
    for (String attr : attributes.keySet()) {
      Method setter = setters.get(attr);
      assertNotNull(attr + " should have a setter", setter);
      assertTrue(setter.getName().startsWith("set"));
      assertEquals(setter.getParameterCount(), 1);

      if (!(attr.equalsIgnoreCase(LOG_LEVEL) || attr.equalsIgnoreCase(SECURITY_LOG_LEVEL))) {
        Class clazz = attributes.get(attr).type();
        try {
          setter.invoke(mock(DistributionConfig.class), any(clazz));
        } catch (Exception e) {
          throw new RuntimeException("Error calling setter " + setter.getName(), e);
        }
      }

    }
  }

  @Test
  public void everyAttrHasValidGetter() {
    for (String attr : attributes.keySet()) {
      Method getter = getters.get(attr);
      assertNotNull(attr + " should have a getter", getter);
      assertTrue(getter.getName().startsWith("get"));
      assertEquals(getter.getParameterCount(), 0);

      if (!(attr.equalsIgnoreCase(LOG_LEVEL) || attr.equalsIgnoreCase(SECURITY_LOG_LEVEL))) {
        Class clazz = attributes.get(attr).type();
        Class returnClass = getter.getReturnType();
        if (returnClass.isPrimitive()) {
          returnClass = classMap.get(returnClass);
        }
        assertEquals(returnClass, clazz);
      }
    }
  }

  @Test
  public void everyGetterSetterSameNameSameType() {
    for (String attr : getters.keySet()) {
      Method getter = getters.get(attr);
      Method setter = setters.get(attr);
      assertNotNull("every getter should have a corresponding setter " + attr, setter);
      String setterName = setter.getName();
      String getterName = getter.getName();
      assertEquals(setterName.substring(setterName.indexOf("set") + 3),
          getterName.substring(getterName.indexOf("get") + 3));
      assertEquals(setter.getParameterTypes()[0], getter.getReturnType());
    }

    for (String attr : setters.keySet()) {
      Method getter = getters.get(attr);
      assertNotNull("every setter should have a corresponding getter: " + attr, getter);
    }
  }

  @Test
  public void everySetterHasAttributeDefined() {
    for (String attr : setters.keySet()) {
      ConfigAttribute configAttribute = attributes.get(attr);
      assertNotNull(attr + " should be defined a ConfigAttribute", configAttribute);
    }
  }

  @Test
  public void everyGetterHasAttributeDefined() {
    for (String attr : getters.keySet()) {
      ConfigAttribute configAttribute = attributes.get(attr);
      assertNotNull(attr + " should be defined a ConfigAttribute", configAttribute);
    }
  }

  @Test
  public void testGetAttributeObject() {
    assertEquals(config.getAttributeObject(LOG_LEVEL), "config");
    assertEquals(config.getAttributeObject(SECURITY_LOG_LEVEL), "config");
    assertEquals(config.getAttributeObject(REDUNDANCY_ZONE), "");
    assertEquals(config.getAttributeObject(ENABLE_CLUSTER_CONFIGURATION).getClass(), Boolean.class);
  }

  @Test
  public void testCheckerChecksValidAttribute() {
    for (String att : checkers.keySet()) {
      System.out.println("att = " + att);
      assertTrue(attributes.containsKey(att));
      Method checker = checkers.get(att);
      assertEquals(checker.getParameterCount(), 1);
      assertEquals("invalid checker: " + checker.getName(), checker.getReturnType(),
          checker.getParameterTypes()[0]);

      // TODO assert checker and setter accepts this same type of parameter
    }
  }

  @Test
  public void testDistributionConfigImplModifiable() {
    // default DistributionConfigImpl contains only 2 modifiable attributes
    List modifiables = new ArrayList<>();
    for (String attName : attNames) {
      if (config.isAttributeModifiable(attName)) {
        modifiables.add(attName);
      }
    }
    assertEquals(modifiables.size(), 2);
    assertEquals(modifiables.get(0), HTTP_SERVICE_PORT);
    assertEquals(modifiables.get(1), JMX_MANAGER_HTTP_PORT);
  }

  @Test
  public void testRuntimeConfigModifiable() {
    InternalDistributedSystem ds = mock(InternalDistributedSystem.class);
    when(ds.getOriginalConfig()).thenReturn(config);
    RuntimeDistributionConfigImpl runtime = new RuntimeDistributionConfigImpl(ds);
    List modifiables = new ArrayList<>();
    for (String attName : attNames) {
      if (runtime.isAttributeModifiable(attName)) {
        modifiables.add(attName);
      }
    }

    assertEquals(modifiables.size(), 10);
    assertEquals(modifiables.get(0), ARCHIVE_DISK_SPACE_LIMIT);
    assertEquals(modifiables.get(1), ARCHIVE_FILE_SIZE_LIMIT);
    assertEquals(modifiables.get(2), HTTP_SERVICE_PORT);
    assertEquals(modifiables.get(3), JMX_MANAGER_HTTP_PORT);
    assertEquals(modifiables.get(4), LOG_DISK_SPACE_LIMIT);
    assertEquals(modifiables.get(5), LOG_FILE_SIZE_LIMIT);
    assertEquals(modifiables.get(6), LOG_LEVEL);
    assertEquals(modifiables.get(7), STATISTIC_ARCHIVE_FILE);
    assertEquals(modifiables.get(8), STATISTIC_SAMPLE_RATE);
    assertEquals(modifiables.get(9), STATISTIC_SAMPLING_ENABLED);
  }

  @Test(expected = IllegalArgumentException.class)
  public void testSetInvalidAttributeObject() {
    config.setAttributeObject("fake attribute", "test", ConfigSource.api());
  }

  @Test(expected = UnmodifiableException.class)
  public void testSetUnmodifiableAttributeObject() {
    config.setAttributeObject(ARCHIVE_DISK_SPACE_LIMIT, 0, ConfigSource.api());
  }

  @Test
  public void testValidAttributeObject() {
    config.setAttributeObject(HTTP_SERVICE_PORT, 8080, ConfigSource.api());
    assertEquals(config.getHttpServicePort(), 8080);
  }

  @Test(expected = IllegalArgumentException.class)
  public void testOutOfRangeAttributeObject() {
    config.setAttributeObject(HTTP_SERVICE_PORT, -1, ConfigSource.api());
  }

  @Test
  public void testLogLevel() {
    config.modifiable = true;
    config.setAttribute(LOG_LEVEL, "config", ConfigSource.api());
    assertEquals(config.getLogLevel(), 700);

    config.setAttributeObject(SECURITY_LOG_LEVEL, "debug", ConfigSource.api());
    assertEquals(config.getSecurityLogLevel(), 500);
  }

  @Test
  public void testLog4jLogLevel() {
    config.modifiable = true;
    config.setAttribute(LOG_LEVEL, "fatal", ConfigSource.api());
    assertEquals(config.getLogLevel(), 1000);
  }

  @Test
  public void testValidLocatorAddress() {
    String address = "81.240.0.1[7056]";
    config.modifiable = true;
    config.setAttributeObject(START_LOCATOR, address, ConfigSource.api());
    assertEquals(config.getStartLocator(), address);
  }

  @Test
  public void testInvalidLocatorAddressDoesntThrowException() {
    String address = "bad.bad[7056]";
    config.modifiable = true;
    // config.setStartLocator(address);
    config.setAttributeObject(START_LOCATOR, address, ConfigSource.api());
  }

  @Test
  public void testAttributesAlwaysModifiable() {
    config.modifiable = false;
    assertTrue(config.isAttributeModifiable(HTTP_SERVICE_PORT));
    assertTrue(config.isAttributeModifiable(JMX_MANAGER_HTTP_PORT));

    config.modifiable = true;
    assertTrue(config.isAttributeModifiable(HTTP_SERVICE_PORT));
    assertTrue(config.isAttributeModifiable(JMX_MANAGER_HTTP_PORT));
  }

  @Test
  public void testSecurityProps() {
    Properties props = new Properties();
    props.put(SECURITY_MANAGER, TestSecurityManager.class.getName());
    props.put(SECURITY_POST_PROCESSOR, TestPostProcessor.class.getName());
    props.put(SECURITY_LOG_LEVEL, "config");
    // add another non-security property to verify it won't get put in the security properties
    props.put(ACK_WAIT_THRESHOLD, 2);

    DistributionConfig config = new DistributionConfigImpl(props);
    // SECURITY_ENABLED_COMPONENTS is automatically added to getSecurityProps
    assertEquals(config.getSecurityProps().size(), 3);
  }

  @Test
  public void testSecurityPropsWithNoSetter() {
    Properties props = new Properties();
    props.put(SECURITY_MANAGER, TestSecurityManager.class.getName());
    props.put(SECURITY_POST_PROCESSOR, TestPostProcessor.class.getName());
    props.put(SECURITY_LOG_LEVEL, "config");
    // add another non-security property to verify it won't get put in the security properties
    props.put(ACK_WAIT_THRESHOLD, 2);
    props.put("security-username", "testName");

    DistributionConfig config = new DistributionConfigImpl(props);
    // SECURITY_ENABLED_COMPONENTS is automatically added to getSecurityProps
    assertEquals(config.getSecurityProps().size(), 4);
  }

  @Test
  public void testSSLEnabledComponents() {
    Properties props = new Properties();
    props.put(MCAST_PORT, "0");
    props.put(SSL_ENABLED_COMPONENTS, "all");

    DistributionConfig config = new DistributionConfigImpl(props);
  }

  @Test(expected = IllegalArgumentException.class)
  public void testSSLEnabledComponentsLegacyFail() {
    Properties props = new Properties();
    props.put(MCAST_PORT, "0");
    props.put(CLUSTER_SSL_ENABLED, "true");
    props.put(HTTP_SERVICE_SSL_ENABLED, "true");
    props.put(SSL_ENABLED_COMPONENTS, "all");

    DistributionConfig config = new DistributionConfigImpl(props);
  }

  @Test
  public void testSSLEnabledComponentsLegacyPass() {
    Properties props = new Properties();
    props.put(MCAST_PORT, "0");
    props.put(CLUSTER_SSL_ENABLED, "true");
    props.put(HTTP_SERVICE_SSL_ENABLED, "true");
    props.put(SSL_ENABLED_COMPONENTS, "");

    DistributionConfig config = new DistributionConfigImpl(props);
  }

  @Test
  public void testSSLEnabledEndpointValidationIsSetDefaultToTrueWhenSetUseDefaultContextIsUsed() {
    Properties props = new Properties();
    props.put(SSL_ENABLED_COMPONENTS, "all");
    props.put(SSL_USE_DEFAULT_CONTEXT, "true");

    DistributionConfig config = new DistributionConfigImpl(props);
    assertThat(config.getSSLEndPointIdentificationEnabled()).isEqualTo(true);
  }

  @Test
  public void testSSLEnabledEndpointValidationIsSetDefaultToFalseWhenDefaultContextNotUsed() {
    Properties props = new Properties();
    props.put(SSL_ENABLED_COMPONENTS, "all");

    DistributionConfig config = new DistributionConfigImpl(props);
    assertThat(config.getSSLEndPointIdentificationEnabled()).isEqualTo(false);
  }

  @Test
  public void testSSLUseEndpointValidationIsSet() {
    Properties props = new Properties();
    props.put(SSL_ENDPOINT_IDENTIFICATION_ENABLED, "true");

    DistributionConfig config = new DistributionConfigImpl(props);
    assertThat(config.getSSLEndPointIdentificationEnabled()).isEqualTo(true);
  }
}
