/*
 * 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.ambari.server.state.kerberos;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.TreeMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * KerberosDescriptor is an implementation of an AbstractKerberosDescriptorContainer that
 * encapsulates an entire Kerberos descriptor hierarchy.
 * <p/>
 * A KerberosDescriptor has the following properties:
 * <ul>
 * <li>services</li>
 * <li>properties</li>
 * <li>identities ({@link org.apache.ambari.server.state.kerberos.AbstractKerberosDescriptorContainer})</li>
 * <li>configurations ({@link org.apache.ambari.server.state.kerberos.AbstractKerberosDescriptorContainer})</li>
 * </ul>
 * <p/>
 * The following (pseudo) JSON Schema will yield a valid KerberosDescriptor
 * <pre>
 *   {
 *      "$schema": "http://json-schema.org/draft-04/schema#",
 *      "title": "KerberosDescriptor",
 *      "description": "Describes a Kerberos descriptor",
 *      "type": "object",
 *      "properties": {
 *        "services": {
 *          "description": "A list of service descriptors",
 *          "type": "array",
 *          "items": {
 *            "title": "KerberosServiceDescriptor"
 *            "type": "{@link org.apache.ambari.server.state.kerberos.KerberosServiceDescriptor}"
 *          }
 *        },
 *        "properties": {
 *          "description": "Global properties that can be used in variable replacements",
 *          "type": "object",
 *          "patternProperties": {
 *            "^[\w\.\_]?$": {}"
 *          }
 *        }
 *        "identities": {
 *          "description": "A list of Kerberos identity descriptors",
 *          "type": "array",
 *          "items": {
 *            "title": "KerberosIdentityDescriptor"
 *            "type": "{@link org.apache.ambari.server.state.kerberos.KerberosIdentityDescriptor}"
 *          }
 *        },
 *        "configurations": {
 *          "description": "A list of relevant configuration blocks",
 *          "type": "array",
 *          "items": {
 *            "title": "KerberosConfigurationDescriptor"
 *            "type": "{@link org.apache.ambari.server.state.kerberos.KerberosConfigurationDescriptor}"
 *          }
 *        }
 *      }
 *   }
 * </pre>
 * <p/>
 * In this implementation,
 * {@link org.apache.ambari.server.state.kerberos.AbstractKerberosDescriptor#name} will be null
 */
public class KerberosDescriptor extends AbstractKerberosDescriptorContainer {

  /**
   * A Map of the "global" properties contained within this KerberosDescriptor
   */
  private Map<String, String> properties = null;

  /**
   * A Map of the services contained within this KerberosDescriptor
   */
  private Map<String, KerberosServiceDescriptor> services = null;


  /**
   * Creates an empty KerberosDescriptor
   */
  public KerberosDescriptor() {
    this(null);
  }

  /**
   * Creates a new KerberosDescriptor
   * <p/>
   * See {@link org.apache.ambari.server.state.kerberos.KerberosDescriptor} for the JSON
   * Schema that may be used to generate this map.
   *
   * @param data a Map of values use to populate the data for the new instance
   * @see org.apache.ambari.server.state.kerberos.KerberosDescriptor
   */
  KerberosDescriptor(Map<?, ?> data) {
    super(data);

    if (data != null) {
      Object list = data.get(Type.SERVICE.getDescriptorPluralName());
      if (list instanceof Collection) {
        for (Object item : (Collection) list) {
          if (item instanceof Map) {
            putService(new KerberosServiceDescriptor((Map<?, ?>) item));
          }
        }
      }

      Object map = data.get("properties");
      if (map instanceof Map) {
        for (Map.Entry<?, ?> entry : ((Map<?, ?>) map).entrySet()) {
          Object value = entry.getValue();
          putProperty(entry.getKey().toString(), (value == null) ? null : value.toString());
        }
      }
    }
  }

  @Override
  public Collection<? extends AbstractKerberosDescriptorContainer> getChildContainers() {
    return (services == null) ? null : Collections.unmodifiableCollection(services.values());
  }

  @Override
  public AbstractKerberosDescriptorContainer getChildContainer(String name) {
    return getService(name);
  }

  /**
   * Set the KerberosServiceDescriptors in this KerberosDescriptor
   *
   * @param services a Map of String to KerberosServiceDescriptor
   */
  public void setServices(Map<String, KerberosServiceDescriptor> services) {
    this.services = (services == null)
        ? null
        : new TreeMap<String, KerberosServiceDescriptor>(services);
  }

  /**
   * Returns a Map of the KerberosServiceDescriptors in this KerberosDescriptor
   *
   * @return a Map of String to KerberosServiceDescriptor
   */
  public Map<String, KerberosServiceDescriptor> getServices() {
    return services;
  }

  /**
   * Gets the KerberosServiceDescriptor with the specified name
   *
   * @param name a String declaring the name of the KerberosServiceDescriptor to retrieve
   * @return the requested KerberosServiceDescriptor or null if not found
   */
  public KerberosServiceDescriptor getService(String name) {
    return ((name == null) || (services == null)) ? null : services.get(name);
  }

  /**
   * Adds or replaces a KerberosServiceDescriptor
   * <p/>
   * If a KerberosServiceDescriptor with the same name already exists in the services Map, it will
   * be replaced; else a new entry will be made.
   *
   * @param service the KerberosServiceDescriptor to put
   */
  public void putService(KerberosServiceDescriptor service) {
    if (service != null) {
      String name = service.getName();

      if (name == null) {
        throw new IllegalArgumentException("The service name must not be null");
      }

      if (services == null) {
        services = new TreeMap<String, KerberosServiceDescriptor>();
      }

      services.put(name, service);

      // Set the service's parent to this KerberosDescriptor
      service.setParent(this);
    }
  }

  /**
   * Set the Map of properties for this KerberosDescriptor
   *
   * @param properties a Map of String to String values
   */
  public void setProperties(Map<String, String> properties) {
    this.properties = (properties == null)
        ? null
        : new TreeMap<String, String>(properties);
  }

  /**
   * Gets the Map of properties for this KerberosDescriptor
   *
   * @return a Map of String to String values
   */
  public Map<String, String> getProperties() {
    return properties;
  }

  /**
   * Gets the value of the property with the specified name
   *
   * @param name a String declaring the name of the property to retrieve
   * @return a String or null if the property was not found
   */
  public String getProperty(String name) {
    return ((name == null) || (properties == null)) ? null : properties.get(name);
  }

  /**
   * Adds or updates a property value
   * <p/>
   * If a property exists with the specified name, replaces its value; else adds a new entry.
   *
   * @param name  a String declaring the name of the property to put
   * @param value a String containing the value of the property to put
   */
  public void putProperty(String name, String value) {
    if (name == null) {
      throw new IllegalArgumentException("The property name must not be null");
    }

    if (properties == null) {
      properties = new TreeMap<String, String>();
    }

    properties.put(name, value);
  }

  /**
   * Updates this KerberosDescriptor with data from another KerberosDescriptor
   * <p/>
   * Properties will be updated if the relevant updated values are not null.
   *
   * @param updates the KerberosDescriptor containing the updated values
   */
  public void update(KerberosDescriptor updates) {
    if (updates != null) {
      Map<String, KerberosServiceDescriptor> updatedServiceDescriptors = updates.getServices();
      if (updatedServiceDescriptors != null) {
        for (Map.Entry<String, KerberosServiceDescriptor> entry : updatedServiceDescriptors.entrySet()) {
          KerberosServiceDescriptor existing = getService(entry.getKey());
          if (existing == null) {
            putService(entry.getValue());
          } else {
            existing.update(entry.getValue());
          }
        }
      }

      Map<String, String> updatedProperties = updates.getProperties();
      if (updatedProperties != null) {
        for (Map.Entry<String, String> entry : updatedProperties.entrySet()) {
          putProperty(entry.getKey(), entry.getValue());
        }
      }
    }

    super.update(updates);
  }

  /**
   * Gets the requested AbstractKerberosDescriptor implementation using a type name and a relevant
   * descriptor name.
   * <p/>
   * This implementation handles service descriptors and delegates to the AbstractKerberosDescriptor
   * implementation to handle component and identity types.
   *
   * @param type a String indicating the type of the requested descriptor
   * @param name a String indicating the name of the requested descriptor
   * @return a AbstractKerberosDescriptor representing the requested descriptor or null if not found
   */
  @Override
  protected AbstractKerberosDescriptor getDescriptor(Type type, String name) {
    if (Type.SERVICE == type) {
      return getService(name);
    } else {
      return super.getDescriptor(type, name);
    }
  }

  /**
   * Creates a Map of values that can be used to create a copy of this KerberosDescriptor
   * or generate the JSON structure described in
   * {@link org.apache.ambari.server.state.kerberos.KerberosDescriptor}
   *
   * @return a Map of values for this KerberosDescriptor
   * @see org.apache.ambari.server.state.kerberos.KerberosDescriptor
   */
  @Override
  public Map<String, Object> toMap() {
    Map<String, Object> map = super.toMap();

    if (services != null) {
      List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
      for (KerberosServiceDescriptor service : services.values()) {
        list.add(service.toMap());
      }
      map.put(Type.SERVICE.getDescriptorPluralName(), list);
    }

    if (properties != null) {
      map.put("properties", new TreeMap<String, String>(properties));
    }

    return map;
  }

  /**
   * Sets the parent (or container) of this descriptor
   * <p/>
   * This implementation prevents the parent from being externally set by always throwing an
   * UnsupportedOperationException.
   *
   * @param parent an AbstractKerberosDescriptor representing the parent (or container) of this
   */
  @Override
  public void setParent(AbstractKerberosDescriptor parent) {
    throw new UnsupportedOperationException("This KerberosDescriptor may not have a parent assigned to it.");
  }

  @Override
  public int hashCode() {
    return super.hashCode() +
        ((getProperties() == null)
            ? 0
            : getProperties().hashCode()) +
        ((getServices() == null)
            ? 0
            : getServices().hashCode());
  }

  @Override
  public boolean equals(Object object) {
    if (object == null) {
      return false;
    } else if (object == this) {
      return true;
    } else if (object.getClass() == KerberosDescriptor.class) {
      KerberosDescriptor descriptor = (KerberosDescriptor) object;
      return super.equals(object) &&
          (
              (getProperties() == null)
                  ? (descriptor.getProperties() == null)
                  : getProperties().equals(descriptor.getProperties())
          ) &&
          (
              (getServices() == null)
                  ? (descriptor.getServices() == null)
                  : getServices().equals(descriptor.getServices())
          );
    } else {
      return false;
    }
  }

  /**
   * Recursively gets the entire set of <code>auth_to_local</code> property names contain within this
   * KerberosDescriptor.
   *
   * @return a Set of String values where each value is in the form of config-type/property_name
   */
  public Set<String> getAllAuthToLocalProperties() {
    Set<String> authToLocalProperties = new HashSet<>();

    Set<String> set;

    set = getAuthToLocalProperties();
    if (set != null) {
      authToLocalProperties.addAll(set);
    }

    if (services != null) {
      for (KerberosServiceDescriptor service : services.values()) {
        Map<String, KerberosComponentDescriptor> components = service.getComponents();

        if (components != null) {
          for (KerberosComponentDescriptor component : components.values()) {
            set = component.getAuthToLocalProperties();
            if (set != null) {
              authToLocalProperties.addAll(set);
            }
          }
        }

        set = service.getAuthToLocalProperties();
        if (set != null) {
          authToLocalProperties.addAll(set);
        }
      }
    }

    return authToLocalProperties;
  }
}
