package com.microsoft.tang;

import com.microsoft.tang.annotations.Name;
import com.microsoft.tang.exceptions.BindException;


final public class StaticConfiguration {
  public interface BindInterface {
    void configure(ConfigurationBuilder cb) throws BindException;
  }
  public static final class AddConfiguration implements BindInterface {
    final StaticConfiguration sc;
    public AddConfiguration(StaticConfiguration sc) {
      this.sc = sc;
    }
    @Override
    public void configure(ConfigurationBuilder cb) throws BindException {
      cb.addConfiguration(sc.build());
    }
  }
  public static final class Register implements BindInterface {
    final Class<?> clazz;
    public Register(Class<?> clazz) { this.clazz = clazz; }
    @Override
    public void configure(ConfigurationBuilder cb) throws BindException {
      cb.register(clazz);
    }
  }
  public static final class RegisterLegacyConstructor implements BindInterface {
    final Class<?> c;
    final Class<?>[] args;
    public RegisterLegacyConstructor(Class<?> c, Class<?>...args) {
      this.c = c;
      this.args = args;
    }
    @Override
    public void configure(ConfigurationBuilder cb) throws BindException {
      cb.registerLegacyConstructor(c, args);
    }
    
  }
  public static final class Bind implements BindInterface {
    final Class<?> inter;
    final Class<?> impl;
    public Bind(Class<?> inter, Class<?> impl) {
      this.inter = inter;
      this.impl = impl;
    }
    @Override
    public void configure(ConfigurationBuilder cb) throws BindException {
      cb.bind(inter,  impl);
    }
  }
  public static final class BindImplementation implements BindInterface {
    final Class<?> inter;
    final Class<?> impl;
    public <T> BindImplementation(Class<T> inter, Class<? extends T> impl) {
      this.inter = inter;
      this.impl = impl;
    }
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Override
    public void configure(ConfigurationBuilder cb) throws BindException {
      cb.bindImplementation((Class)inter,  (Class)impl);
    }
  }
  public static final class BindSingletonImplementation implements BindInterface {
    final Class<?> inter;
    final Class<?> impl;
    public <T> BindSingletonImplementation(Class<T> inter, Class<? extends T> impl) {
      this.inter = inter;
      this.impl = impl;
    }
    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public void configure(ConfigurationBuilder cb) throws BindException {
      cb.bindSingletonImplementation((Class)inter, (Class)impl);
    }
  }
  public static final class BindSingleton implements BindInterface {
    final Class<?> singleton;
    public <T> BindSingleton(Class<T> singleton) {
      this.singleton = singleton;
    }
    @Override
    public void configure(ConfigurationBuilder cb) throws BindException {
      cb.bindSingleton(singleton);
    }
  }
  public static final class BindNamedParameter implements BindInterface {
    final Class<? extends Name<?>> name;
    final String value;
    public <T> BindNamedParameter(Class<? extends Name<T>> name, String value) {
      this.name = name;
      this.value = value;
    }
    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public void configure(ConfigurationBuilder cb) throws BindException {
      cb.bindNamedParameter((Class)name,  value);
    }
  }
  public static final class BindConstructor implements BindInterface {
    final Class<?> inter;
    final Class<? extends ExternalConstructor<?>> constructor;
    public <T> BindConstructor(Class<T> inter, Class<? extends ExternalConstructor<T>> constructor) {
      this.inter = inter;
      this.constructor = constructor;
    }
    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public void configure(ConfigurationBuilder cb) throws BindException {
      cb.bindConstructor((Class)inter, (Class)constructor);
    }
  }
  private final BindInterface[] b;
  private Configuration memo;
  
  public StaticConfiguration(BindInterface... b) {
    this.b = b;
  }
  
  public Configuration build() throws BindException {
    if(memo == null) {
      ConfigurationBuilder cb = Tang.Factory.getTang().newConfigurationBuilder();
      for(BindInterface bi : b) {
        bi.configure(cb);
      }
      memo = cb.build();
    }
    return memo;
  }
}

@@ -3012,24 +3012,49 @@
 ring value;%0A
+    final Class%3C?%3E impl;%0A
     public %3C
@@ -3168,24 +3168,209 @@
 ue = value;%0A
+      this.impl = null;%0A    %7D%0A    public %3CT%3E BindNamedParameter(Class%3C? extends Name%3CT%3E%3E name, Class%3CT%3E impl) %7B%0A      this.name = name;%0A      this.impl = impl;%0A      this.value = null;%0A
     %7D%0A    @S
@@ -3494,32 +3494,60 @@
 BindException %7B%0A
+      if(value != null) %7B%0A  
       cb.bindNam
@@ -3580,16 +3580,96 @@
 value);%0A
+      %7D else %7B%0A        cb.bindNamedParameter((Class)name, (Class)impl);%0A      %7D%0A
     %7D%0A  

add static configuration constructor for named instances