/** @author <a href="mailto:[email protected]">Lincoln Baxter, III</a> */
public class ForgeArchiveImpl extends ContainerBase<ForgeArchive>
    implements ForgeArchive, RepositoryForgeArchive {
  // -------------------------------------------------------------------------------------||
  // Class Members ----------------------------------------------------------------------||
  // -------------------------------------------------------------------------------------||

  @SuppressWarnings("unused")
  private static final Logger log = Logger.getLogger(ForgeArchiveImpl.class.getName());

  /** Path to the web inside of the Archive. */
  private static final ArchivePath PATH_ROOT = ArchivePaths.root();

  /** Path to the classes inside of the Archive. */
  private static final ArchivePath PATH_CLASSES = ArchivePaths.create(PATH_ROOT, "");

  /** Path to the libraries inside of the Archive. */
  private static final ArchivePath PATH_LIBRARY = ArchivePaths.create(PATH_ROOT, "lib");

  /** Path to the manifests inside of the Archive. */
  private static final ArchivePath PATH_MANIFEST = ArchivePaths.create("META-INF");

  /** Path to the forge XML config file inside of the Archive. */
  private static final ArchivePath PATH_FORGE_XML = ArchivePaths.create("META-INF/forge.xml");

  /** Path to web archive service providers. */
  private static final ArchivePath PATH_SERVICE_PROVIDERS =
      ArchivePaths.create(PATH_CLASSES, "META-INF/services");

  private List<AddonDependencyEntry> addonDependencies = new ArrayList<AddonDependencyEntry>();

  private String repository;

  // -------------------------------------------------------------------------------------||
  // Instance Members -------------------------------------------------------------------||
  // -------------------------------------------------------------------------------------||

  // -------------------------------------------------------------------------------------||
  // Constructor ------------------------------------------------------------------------||
  // -------------------------------------------------------------------------------------||

  /**
   * Create a new {@link ForgeArchive} with any type storage engine as backing.
   *
   * @param delegate The storage backing.
   */
  public ForgeArchiveImpl(final Archive<?> delegate) {
    super(ForgeArchive.class, delegate);
  }

  // -------------------------------------------------------------------------------------||
  // Required Implementations -----------------------------------------------------------||
  // -------------------------------------------------------------------------------------||

  /**
   * {@inheritDoc}
   *
   * @see org.jboss.shrinkwrap.impl.base.container.ContainerBase#getManifestPath()
   */
  @Override
  protected ArchivePath getManifestPath() {
    return PATH_MANIFEST;
  }

  protected ArchivePath getForgeXMLPath() {
    return PATH_FORGE_XML;
  }

  /**
   * {@inheritDoc}
   *
   * @see org.jboss.shrinkwrap.impl.base.container.ContainerBase#getClassesPath()
   */
  @Override
  protected ArchivePath getClassesPath() {
    return PATH_CLASSES;
  }

  /**
   * {@inheritDoc}
   *
   * @see org.jboss.shrinkwrap.impl.base.container.ContainerBase#getLibraryPath()
   */
  @Override
  protected ArchivePath getLibraryPath() {
    return PATH_LIBRARY;
  }

  protected ArchivePath getServiceProvidersPath() {
    return PATH_SERVICE_PROVIDERS;
  }

  @Override
  protected ArchivePath getResourcePath() {
    return PATH_CLASSES;
  }

  @Override
  public ForgeArchive setAsForgeXML(final Asset resource) throws IllegalArgumentException {
    Validate.notNull(resource, "Resource should be specified");
    return add(resource, getForgeXMLPath());
  }

  @Override
  public ForgeArchive addAsAddonDependencies(AddonDependencyEntry... dependencies) {
    if (dependencies != null) addonDependencies.addAll(Arrays.asList(dependencies));
    return this;
  }

  @Override
  public List<AddonDependencyEntry> getAddonDependencies() {
    return addonDependencies;
  }

  @Override
  public ForgeArchive addBeansXML() {
    addAsManifestResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml"));
    return this;
  }

  @Override
  public ForgeArchive addBeansXML(Asset resource) {
    addAsManifestResource(resource, ArchivePaths.create("beans.xml"));
    return this;
  }

  @Override
  public String getAddonRepository() {
    return repository;
  }

  @Override
  public RepositoryForgeArchive setAddonRepository(String repository) {
    this.repository = repository;
    return this;
  }

  private static final String SERVICE_REGISTRATION_FILE_NAME =
      "org.jboss.forge.furnace.services.Exported";

  @Override
  public ForgeArchive addAsLocalServices(Class<?>... serviceTypes) {
    addAsServiceProvider(AddonLifecycleProvider.class, LocalServices.class);
    addPackages(true, LocalServices.class.getPackage());
    Set<String> typeNames = new LinkedHashSet<String>();
    for (Class<?> type : serviceTypes) {
      typeNames.add(type.getName());
    }

    addAsServiceProvider(
        SERVICE_REGISTRATION_FILE_NAME, typeNames.toArray(new String[typeNames.size()]));
    return this;
  }
}