/***********************************************************
Copyright (C) 2018 VeriSign, Inc.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

http://www.verisign.com/nds/naming/namestore/techdocs.html
 ***********************************************************/

package com.verisign.epp.serverstub;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.verisign.epp.codec.gen.EPPCodecComponent;
import com.verisign.epp.codec.registry.policy.EPPRegistryZoneInterface;
import com.verisign.epp.framework.EPPRegistryPolicyAdapter;
import com.verisign.epp.util.EPPEnv;

/**
 * {@code RegistryPolicyCompositeAdapter} will execute each of the configured
 * Registry Policy Adapters and executes each one to adapt all of the registry
 * policy EPP extensions to zone policy extensions and vice-versa.
 */
public class RegistryPolicyCompositeAdapter {

      private static Logger cat = LoggerFactory.getLogger(RegistryPolicyCompositeAdapter.class);
        

  /**
   * List of configured registry policy adapters. There should be one per
   * registry policy extension version.
   */
  private static List<EPPRegistryPolicyAdapter> adapters;

  /**
   * Static initializer that loads the adapter {@code EPPRegistryPolicyAdapter}
   * instances.
   */
  static {
    adapters = new ArrayList<EPPRegistryPolicyAdapter>();

    List<String> theAdapters = EPPEnv.getRegistryPolicyAdapters();

    // Any policy adapters defined?
    if (theAdapters != null) {

      // Add each policy adapter
      for (String theAdapter : theAdapters) {
        try {
          adapters
                .add((EPPRegistryPolicyAdapter) Class.forName(theAdapter).getDeclaredConstructor().newInstance());
        }
        catch (Exception ex) {
          cat.error("Exception loading EPPRegistryPolicyAdapter class \"" + theAdapter + "\": " + ex);
        }
      }
    }

  }

  /**
   * Adapt a list of EPP extensions used with a registry create or update to a
   * list of matching zone policy extensions. It is assumed that there will be
   * an {@code EPPRegistryPolicyAdapter} for each versioned policy extension
   * that will be used to extract the contained zone policy information in a
   * matching EPP extension.
   * 
   * @param aEppExtensions
   *           List of EPP extensions to adapt to a zone policy extension.
   * 
   * @return Matching zone policy extensions if matches found; empty list
   *         otherwise.
   */
  public List<EPPRegistryZoneInterface> eppExtToZoneExt(List<EPPCodecComponent> aEppExtensions) {
    cat.debug("eppExtToZoneExt: enter");
    List<EPPRegistryZoneInterface> theZoneExts = new ArrayList<EPPRegistryZoneInterface>();

    for (EPPRegistryPolicyAdapter theAdapter : adapters) {
      EPPRegistryZoneInterface theZoneExt = theAdapter.eppExtToZoneExt(aEppExtensions);

      if (theZoneExt != null) {
        cat.debug("eppExtToZoneExt: adding zone extension " + theZoneExt.getClass().getName());
        theZoneExts.add(theZoneExt);
      }
    }

    cat.debug("eppExtToZoneExt: exit");
    return theZoneExts;
  }

  /**
   * Adapt a list of zone policy extensions available for the zone to a
   * matching list of EPP extensions for an info response.
   * 
   * @param aZoneExtensions
   *           List of zone policy extensions to adapt to an EPP extension for
   *           an info response.
   * @return Matching EPP extensions for an info response if matches found;
   *         empty list otherwise.
   */
  public List<EPPCodecComponent> zoneExtToEppExt(List<EPPRegistryZoneInterface> aZoneExtensions) {
    cat.debug("zoneExtToEppExt: enter");
    List<EPPCodecComponent> TheEppExts = new ArrayList<EPPCodecComponent>();

    for (EPPRegistryPolicyAdapter theAdapter : adapters) {
      EPPCodecComponent theEppExt = theAdapter.zoneExtToEppExt(aZoneExtensions);

      if (theEppExt != null) {
        cat.debug("zoneExtToEppExt: adding EPP extension " + theEppExt.getClass().getName());
        TheEppExts.add(theEppExt);
      }
    }

    cat.debug("zoneExtToEppExt: exit");
    return TheEppExts;
  }

  /**
   * Adapts the registered set of policy adapters to a list of system policy
   * extensions that can be added to a registry system info response.
   * 
   * @return List of system policy extensions associated with registered
   *         adapters.
   */
  public List<EPPCodecComponent> getSystemExts() {
    cat.debug("getSystemExts: enter");
    List<EPPCodecComponent> TheEppExts = new ArrayList<EPPCodecComponent>();

    for (EPPRegistryPolicyAdapter theAdapter : adapters) {
      EPPCodecComponent theEppExt = theAdapter.getSystemExt();

      if (theEppExt != null) {
        cat.debug("getSystemExts: adding EPP extension " + theEppExt.getClass().getName());
        TheEppExts.add(theEppExt);
      }
    }

    cat.debug("getSystemExts: exit");
    return TheEppExts;
  }

}
