/**
 * Copyright (C) 2011 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.grapher;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.inject.Binding;
import com.google.inject.spi.ConstructorBinding;
import com.google.inject.spi.DefaultBindingTargetVisitor;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.HasDependencies;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.InstanceBinding;
import com.google.inject.spi.ProviderInstanceBinding;
import java.lang.reflect.Member;
import java.util.Collection;
import java.util.List;

/**
 * Default node creator.
 *
 * @author bojand@google.com (Bojan Djordjevic)
 */
final class DefaultNodeCreator implements NodeCreator {
  @Override public Iterable<Node> getNodes(Iterable<Binding<?>> bindings) {
    List<Node> nodes = Lists.newArrayList();
    NodeVisitor visitor = new NodeVisitor();
    for (Binding<?> binding : bindings) {
      nodes.addAll(binding.acceptTargetVisitor(visitor));
    }
    return nodes;
  }

  /**
   * {@link BindingTargetVisitor} that adds nodes to the graph based on the visited {@link Binding}.
   */
  private static final class NodeVisitor
      extends DefaultBindingTargetVisitor<Object, Collection<Node>> {

    /** Returns a new interface node for the given {@link Binding}. */
    private InterfaceNode newInterfaceNode(Binding<?> binding) {
      return new InterfaceNode(NodeId.newTypeId(binding.getKey()), binding.getSource());
    }

    /**
     * Returns a new implementation node for the given binding.
     *
     * @param binding binding for the node to create
     * @param members members to add to the node
     * @return implementation node for the given binding
     */
    private ImplementationNode newImplementationNode(Binding<?> binding,
        Collection<Member> members) {
      return new ImplementationNode(NodeId.newTypeId(binding.getKey()), binding.getSource(),
          members);
    }

    /**
     * Returns a new instance node for the given {@link Binding}.
     *
     * @param binding binding for the node to create
     * @param instance value of the instance
     * @return instance node for the given binding
     */
    private <T extends Binding<?> & HasDependencies> InstanceNode newInstanceNode(T binding,
        Object instance) {
      Collection<Member> members = Lists.newArrayList();
      for (Dependency<?> dependency : binding.getDependencies()) {
        InjectionPoint injectionPoint = dependency.getInjectionPoint();

        if (injectionPoint != null) {
          members.add(injectionPoint.getMember());
        }
      }
      return new InstanceNode(NodeId.newInstanceId(binding.getKey()), binding.getSource(), instance,
          members);
    }

    /**
     * Visitor for {@link ConstructorBinding}s. These are for classes that Guice will instantiate to
     * satisfy injection requests.
     */
    @Override public Collection<Node> visit(ConstructorBinding<?> binding) {
      Collection<Member> members = Lists.newArrayList();
      members.add(binding.getConstructor().getMember());
      for (InjectionPoint injectionPoint : binding.getInjectableMembers()) {
        members.add(injectionPoint.getMember());
      }

      return ImmutableList.<Node>of(newImplementationNode(binding, members));
    }

    /**
     * Visitor for {@link InstanceBinding}. We render two nodes in this case: an interface node for
     * the binding's {@link Key}, and then an implementation node for the instance {@link Object}
     * itself.
     */
    @Override public Collection<Node> visit(InstanceBinding<?> binding) {
      return ImmutableList.<Node>of(newInterfaceNode(binding), newInstanceNode(binding,
          binding.getInstance()));
    }

    /**
     * Same as {@link #visit(InstanceBinding)}, but the binding edge is
     * {@link BindingEdgeType#PROVIDER}.
     */
    @Override public Collection<Node> visit(ProviderInstanceBinding<?> binding) {
      return ImmutableList.<Node>of(newInterfaceNode(binding), newInstanceNode(binding,
          binding.getProviderInstance()));
    }

    @Override public Collection<Node> visitOther(Binding<?> binding) {
      return ImmutableList.<Node>of(newInterfaceNode(binding));
    }
  }
}
