/**
 * Copyright (C) 2008 Google Inc.
 *
 * Licensed 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 com.google.inject.internal;

import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Binder;
import com.google.inject.Binding;
import com.google.inject.ConfigurationException;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.Scope;
import com.google.inject.TypeLiteral;
import com.google.inject.binder.AnnotatedBindingBuilder;
import com.google.inject.binder.AnnotatedConstantBindingBuilder;
import com.google.inject.binder.AnnotatedElementBuilder;
import com.google.inject.binder.ConstantBindingBuilder;
import com.google.inject.binder.LinkedBindingBuilder;
import com.google.inject.binder.ScopedBindingBuilder;
import com.google.inject.spi.BindingScopingVisitor;
import com.google.inject.spi.BindingTargetVisitor;
import com.google.inject.spi.DefaultBindingTargetVisitor;
import com.google.inject.spi.ElementVisitor;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.Message;
import com.google.inject.spi.PrivateEnvironment;
import com.google.inject.util.Providers;
import java.lang.annotation.Annotation;
import java.util.Set;

/**
 * Immutable snapshot of a request to bind a value.
 *
 * @author jessewilson@google.com (Jesse Wilson)
 */
public final class ModuleBinding<T> implements Binding<T> {

  public static final String IMPLEMENTATION_ALREADY_SET = "Implementation is set more than once.";
  public static final String SINGLE_INSTANCE_AND_SCOPE
      = "Setting the scope is not permitted when binding to a single instance.";
  public static final String SCOPE_ALREADY_SET = "Scope is set more than once.";
  public static final String BINDING_TO_NULL = "Binding to null instances is not allowed. "
      + "Use toProvider(Providers.of(null)) if this is your intended behaviour.";
  public static final String CONSTANT_VALUE_ALREADY_SET = "Constant value is set more than once.";
  public static final String ANNOTATION_ALREADY_SPECIFIED
      = "More than one annotation is specified for this binding.";

  private final Key<?> NULL_KEY = Key.get(Void.class);

  private static final Target<Object> EMPTY_TARGET = new Target<Object>() {
    public <V> V acceptTargetVisitor(BindingTargetVisitor<? super Object, V> visitor) {
      return visitor.visitUntargetted();
    }
  };

  private static final Scoping EMPTY_SCOPING = new AbstractScoping() {
    public <V> V acceptVisitor(BindingScopingVisitor<V> visitor) {
      return visitor.visitNoScoping();
    }
  };

  private static final BindingTargetVisitor<Object, Boolean> SUPPORTS_SCOPES
      = new DefaultBindingTargetVisitor<Object, Boolean>() {
    @Override public Boolean visitInstance(Object instance, Set<InjectionPoint> injectionPoints) {
      return false;
    }

    @Override protected Boolean visitOther() {
      return true;
    }
  };

  private final Object source;
  private Key<T> key;

  @SuppressWarnings("unchecked")
  private Target<T> target = (Target<T>) EMPTY_TARGET;
  private Scoping scoping = EMPTY_SCOPING;

  public ModuleBinding(Object source, Key<T> key) {
    this.source = checkNotNull(source, "source");
    this.key = checkNotNull(key, "key");
  }

  public ModuleBinding(Object source) {
    @SuppressWarnings("unchecked") // unsafe, but we won't ever return this (Key.get fails)
    Key<T> NULL_KEY_OF_T = (Key<T>) NULL_KEY;

    this.source = checkNotNull(source);
    this.key = NULL_KEY_OF_T;
  }

  public Object getSource() {
    return source;
  }

  /**
   * Returns the scoped provider guice uses to fulfill requests for this
   * binding.
   */
  public Provider<T> getProvider() {
    throw new UnsupportedOperationException();
  }

  public <V> V acceptVisitor(ElementVisitor<V> visitor) {
    return visitor.visitBinding(this);
  }

  public Key<T> getKey() {
    return key;
  }

  public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
    return target.acceptTargetVisitor(visitor);
  }

  public <V> V acceptScopingVisitor(BindingScopingVisitor<V> visitor) {
    return scoping.acceptVisitor(visitor);
  }

  private boolean keyTypeIsSet() {
    return !Void.class.equals(key.getTypeLiteral().getType());
  }

  @Override public String toString() {
    return "bind " + key
        + (target == EMPTY_TARGET ? "" : (" to " + target))
        + (scoping == EMPTY_SCOPING ? "" : (" in " + scoping));
  }

  private static abstract class AbstractScoping implements Scoping {
    public Scope getScope() {
      return null;
    }
    public Class<? extends Annotation> getScopeAnnotation() {
      return null;
    }
  }

  public RegularBuilder regularBuilder(Binder binder) {
    return new RegularBuilder(binder);
  }


  /** @param binder the binder where errors will be reported. */
  public ExposureBuilder<T> exposedKeyBuilder(Binder binder,
      final PrivateEnvironment privateEnvironment) {
    if (target != EMPTY_TARGET) {
      throw new AssertionError();
    }

    target = new Target<T>() {
      public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
        return visitor.visitExposed(privateEnvironment);
      }
    };

    return new ExposureBuilder<T>(this, binder);
  }

  /**
   * Write access to the internal state of this element. Not for use by the public API.
   */
  public class RegularBuilder implements AnnotatedBindingBuilder<T> {
    private final Binder binder;

    RegularBuilder(Binder binder) {
      this.binder = binder.skipSources(RegularBuilder.class);
    }

    public LinkedBindingBuilder<T> annotatedWith(Class<? extends Annotation> annotationType) {
      checkNotNull(annotationType, "annotationType");
      checkNotAnnotated();
      key = Key.get(key.getTypeLiteral(), annotationType);
      return this;
    }

    public LinkedBindingBuilder<T> annotatedWith(Annotation annotation) {
      checkNotNull(annotation, "annotation");
      checkNotAnnotated();
      key = Key.get(key.getTypeLiteral(), annotation);
      return this;
    }

    public ScopedBindingBuilder to(final Class<? extends T> implementation) {
      return to(Key.get(implementation));
    }

    public ScopedBindingBuilder to(
        final TypeLiteral<? extends T> implementation) {
      return to(Key.get(implementation));
    }

    public ScopedBindingBuilder to(final Key<? extends T> targetKey) {
      checkNotNull(targetKey, "targetKey");
      checkNotTargetted();
      target = new Target<T>() {
        public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
          return visitor.visitKey(targetKey);
        }
        @Override public String toString() {
          return String.valueOf(targetKey);
        }
      };
      return this;
    }

    public void toInstance(final T instance) {
      checkNotTargetted();

      if (instance == null) {
        binder.addError(BINDING_TO_NULL);
        // we finish the binding to prevent additional errors
        toProvider(Providers.<T>of(null));
        return;
      }

      // lookup the injection points, adding any errors to the binder's errors list
      Set<InjectionPoint> injectionPoints;
      try {
        injectionPoints = InjectionPoint.forInstanceMethodsAndFields(instance.getClass());
      } catch (ConfigurationException e) {
        for (Message message : e.getErrorMessages()) {
          binder.addError(message);
        }
        injectionPoints = e.getPartialValue();
      }
      target = new InstanceTarget<T>(instance, injectionPoints);
    }

    public ScopedBindingBuilder toProvider(final Provider<? extends T> provider) {
      checkNotNull(provider, "provider");
      checkNotTargetted();

      // lookup the injection points, adding any errors to the binder's errors list
      Set<InjectionPoint> injectionPoints;
      try {
        injectionPoints = InjectionPoint.forInstanceMethodsAndFields(provider.getClass());
      } catch (ConfigurationException e) {
        for (Message message : e.getErrorMessages()) {
          binder.addError(message);
        }
        injectionPoints = e.getPartialValue();
      }

      final Set<InjectionPoint> injectionPointsFinal = injectionPoints;
      target = new Target<T>() {
        public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
          return visitor.visitProvider(provider, injectionPointsFinal);
        }
      };
      return this;
    }

    public ScopedBindingBuilder toProvider(
        Class<? extends Provider<? extends T>> providerType) {
      return toProvider(Key.get(providerType));
    }

    public ScopedBindingBuilder toProvider(
        final Key<? extends Provider<? extends T>> providerKey) {
      checkNotNull(providerKey, "providerKey");
      checkNotTargetted();
      target = new Target<T>() {
        public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
          return visitor.visitProviderKey(providerKey);
        }
      };
      return this;
    }

    public void in(final Class<? extends Annotation> scopeAnnotation) {
      checkNotNull(scopeAnnotation, "scopeAnnotation");
      checkNotScoped();

      scoping = new AbstractScoping() {
        @Override public Class<? extends Annotation> getScopeAnnotation() {
          return scopeAnnotation;
        }
        public <V> V acceptVisitor(BindingScopingVisitor<V> visitor) {
          return visitor.visitScopeAnnotation(scopeAnnotation);
        }
        @Override public String toString() {
          return scopeAnnotation.getName();
        }
      };
    }

    public void in(final Scope scope) {
      checkNotNull(scope, "scope");
      checkNotScoped();
      scoping = new AbstractScoping() {
        @Override public Scope getScope() {
          return scope;
        }
        public <V> V acceptVisitor(BindingScopingVisitor<V> visitor) {
          return visitor.visitScope(scope);
        }
        @Override public String toString() {
          return String.valueOf(scope);
        }
      };
    }

    public void asEagerSingleton() {
      checkNotScoped();
      scoping = new AbstractScoping() {
        public <V> V acceptVisitor(BindingScopingVisitor<V> visitor) {
          return visitor.visitEagerSingleton();
        }
        @Override public String toString() {
          return "eager singleton";
        }
      };
    }

    private void checkNotTargetted() {
      if (target != EMPTY_TARGET) {
        binder.addError(IMPLEMENTATION_ALREADY_SET);
      }
    }

    private void checkNotAnnotated() {
      if (ModuleBinding.this.key.getAnnotationType() != null) {
        binder.addError(ANNOTATION_ALREADY_SPECIFIED);
      }
    }

    private void checkNotScoped() {
      @SuppressWarnings("unchecked") BindingTargetVisitor<T,Boolean> supportsScopesOfT
          = (BindingTargetVisitor<T,Boolean>) SUPPORTS_SCOPES;

      // Scoping isn't allowed when we have only one instance.
      if (!target.acceptTargetVisitor(supportsScopesOfT)) {
        binder.addError(SINGLE_INSTANCE_AND_SCOPE);
        return;
      }

      if (scoping != EMPTY_SCOPING) {
        binder.addError(SCOPE_ALREADY_SET);
      }
    }

    @Override public String toString() {
      String type = key.getAnnotationType() == null
          ? "AnnotatedBindingBuilder<"
          : "LinkedBindingBuilder<";
      return type + key.getTypeLiteral() + ">";
    }
  }

  public ConstantBuilder constantBuilder(Binder binder) {
    return new ConstantBuilder(binder);
  }

  /**
   * Package-private write access to the internal state of this element.
   */
  class ConstantBuilder implements AnnotatedConstantBindingBuilder, ConstantBindingBuilder {
    private final Binder binder;

    ConstantBuilder(Binder binder) {
      this.binder = binder.skipSources(ConstantBuilder.class);
    }

    public ConstantBindingBuilder annotatedWith(final Class<? extends Annotation> annotationType) {
      checkNotNull(annotationType, "annotationType");
      if (key.getAnnotationType() != null) {
        binder.addError(ANNOTATION_ALREADY_SPECIFIED);
      } else {
        key = Key.get(key.getTypeLiteral(), annotationType);
      }
      return this;
    }

    public ConstantBindingBuilder annotatedWith(final Annotation annotation) {
      checkNotNull(annotation, "annotation");
      if (key.getAnnotationType() != null) {
        binder.addError(ANNOTATION_ALREADY_SPECIFIED);
      } else {
        key = Key.get(key.getTypeLiteral(), annotation);
      }
      return this;
    }

    public void to(final String value) {
      to(String.class, value);
    }

    public void to(final int value) {
      to(Integer.class, value);
    }

    public void to(final long value) {
      to(Long.class, value);
    }

    public void to(final boolean value) {
      to(Boolean.class, value);
    }

    public void to(final double value) {
      to(Double.class, value);
    }

    public void to(final float value) {
      to(Float.class, value);
    }

    public void to(final short value) {
      to(Short.class, value);
    }

    public void to(final char value) {
      to(Character.class, value);
    }

    public void to(final Class<?> value) {
      to(Class.class, value);
    }

    public <E extends Enum<E>> void to(final E value) {
      to(value.getDeclaringClass(), value);
    }

    private void to(Class<?> type, Object instance) {
      // this type will define T, so these assignments are safe
      @SuppressWarnings("unchecked")
      Class<T> typeAsClassT = (Class<T>) type;
      @SuppressWarnings("unchecked")
      T instanceAsT = (T) instance;

      if (keyTypeIsSet()) {
        binder.addError(CONSTANT_VALUE_ALREADY_SET);
        return;
      }

      if (key.getAnnotation() != null) {
        key = Key.get(typeAsClassT, key.getAnnotation());
      } else if (key.getAnnotationType() != null) {
        key = Key.get(typeAsClassT, key.getAnnotationType());
      } else {
        key = Key.get(typeAsClassT);
      }

      ModuleBinding.this.target = new InstanceTarget<T>(instanceAsT,
          ImmutableSet.<InjectionPoint>of());

      if (instanceAsT == null) {
        binder.addError(BINDING_TO_NULL);
      }
    }

    @Override public String toString() {
      return key.getAnnotationType() == null
          ? "AnnotatedConstantBindingBuilder"
          : "ConstantBindingBuilder";
    }
  }

  /**
   * For private binder's expose() method.
   */
  public static class ExposureBuilder<T> implements AnnotatedElementBuilder {
    private ModuleBinding<T> binding;
    private final Binder binder;

    public ExposureBuilder(ModuleBinding<T> binding, Binder binder) {
      this.binding = binding;
      this.binder = binder;
    }

    public void annotatedWith(Class<? extends Annotation> annotationType) {
      checkNotNull(annotationType, "annotationType");
      checkNotAnnotated();
      binding.key = Key.get(binding.key.getTypeLiteral(), annotationType);
    }

    public void annotatedWith(Annotation annotation) {
      checkNotNull(annotation, "annotation");
      checkNotAnnotated();
      binding.key = Key.get(binding.key.getTypeLiteral(), annotation);
    }

    public Key<?> getKey() {
      return binding.key;
    }

    private void checkNotAnnotated() {
      if (binding.key.getAnnotationType() != null) {
        binder.addError(ANNOTATION_ALREADY_SPECIFIED);
      }
    }

    @Override public String toString() {
      return "AnnotatedElementBuilder";
    }
  }

  /** A binding target, which provides instances from a specific key. */
  private interface Target<T> {
    <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor);
  }

  /** Immutable snapshot of a binding scope. */
  private interface Scoping {
    <V> V acceptVisitor(BindingScopingVisitor<V> visitor);
  }

  static class InstanceTarget<T> implements Target<T> {
    private final T instance;
    private final ImmutableSet<InjectionPoint> injectionPoints;

    public InstanceTarget(T instance, Set<InjectionPoint> injectionPoints) {
      this.instance = instance;
      this.injectionPoints = ImmutableSet.copyOf(injectionPoints);
    }

    public <V> V acceptTargetVisitor(BindingTargetVisitor<? super T, V> visitor) {
      return visitor.visitInstance(instance, injectionPoints);
    }
  }
}
