/*
 * Copyright (c) 2011 Google Inc.
 *
 * All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
 * Public License v1.0 which accompanies this distribution, and is available at
 *
 * http://www.eclipse.org/legal/epl-v10.html
 */
package com.google.eclipse.protobuf.scoping;

import static com.google.eclipse.protobuf.scoping.OptionType.typeOf;
import static java.util.Collections.emptySet;

import java.util.*;

import org.eclipse.emf.ecore.*;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.impl.*;

import com.google.eclipse.protobuf.model.util.*;
import com.google.eclipse.protobuf.protobuf.*;
import com.google.eclipse.protobuf.protobuf.Enum;
import com.google.inject.Inject;

/**
 * Custom scoping description.
 *
 * @author alruiz@google.com (Alex Ruiz)
 *
 * @see <a href="http://www.eclipse.org/Xtext/documentation/latest/xtext.html#scoping">Xtext Scoping</a>
 */
public class ProtobufScopeProvider extends AbstractDeclarativeScopeProvider implements Scoping {

  private static final boolean DO_NOT_IGNORE_CASE = false;

  @Inject private AstWalker astWalker;
  @Inject private CustomOptionFieldScopeFinder customOptionFieldScopeFinder;
  @Inject private CustomOptionScopeFinder customOptionScopeFinder;
  @Inject private ProtoDescriptorProvider descriptorProvider;
  @Inject private FieldNotationScopeFinder fieldNotationScopeFinder;
  @Inject private ModelFinder modelFinder;
  @Inject private LiteralDescriptions literalDescriptions;
  @Inject private NativeOptionDescriptions nativeOptionDescriptions;
  @Inject private Options options;
  @Inject private TypeScopeFinder typeScopeFinder;

  @SuppressWarnings("unused") public IScope scope_ComplexTypeLink_target(ComplexTypeLink link, EReference r) {
    EObject c = link.eContainer();
    if (c instanceof MessageField) { return createScope(allPossibleTypesFor((MessageField) c)); }
    Set<IEObjectDescription> descriptions = emptySet();
    return createScope(descriptions);
  }

  @Override public Collection<IEObjectDescription> allPossibleTypesFor(MessageField field) {
    return astWalker.traverseAst(field, typeScopeFinder, ComplexType.class);
  }

  @SuppressWarnings("unused") public IScope scope_ExtensibleTypeLink_target(ExtensibleTypeLink link, EReference r) {
    return createScope(extensibleTypesFor(link));
  }

  @Override public Collection<IEObjectDescription> allPossibleTypesFor(TypeExtension extension) {
    return extensibleTypesFor(extension);
  }

  private Collection<IEObjectDescription> extensibleTypesFor(EObject o) {
    Protobuf root = modelFinder.rootOf(o);
    return astWalker.traverseAst(root, typeScopeFinder, ExtensibleType.class);
  }

  @SuppressWarnings("unused") public IScope scope_MessageLink_target(MessageLink link, EReference r) {
    return createScope(messagesFor(link));
  }

  @Override public Collection<IEObjectDescription> allPossibleMessagesFor(Rpc rpc) {
    return messagesFor(rpc);
  }

  private Collection<IEObjectDescription> messagesFor(EObject o) {
    Protobuf root = modelFinder.rootOf(o);
    return astWalker.traverseAst(root, typeScopeFinder, Message.class);
  }

  @SuppressWarnings("unused") public IScope scope_LiteralLink_target(LiteralLink link, EReference r) {
    EObject container = link.eContainer();
    Enum anEnum = null;
    if (container instanceof DefaultValueFieldOption) {
      container = container.eContainer();
    }
    if (container instanceof NativeOption) {
      ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
      IndexedElement e = options.rootSourceOf((Option) container);
      anEnum = descriptor.enumTypeOf((MessageField) e);
    }
    if (container instanceof CustomOption) {
      CustomOption option = (CustomOption) container;
      container = options.sourceOf(option);
    }
    if (container instanceof NativeFieldOption) {
      ProtoDescriptor descriptor = descriptorProvider.primaryDescriptor();
      IndexedElement c = options.rootSourceOf((FieldOption) container);
      anEnum = descriptor.enumTypeOf((MessageField) c);
    }
    if (container instanceof CustomFieldOption) {
      CustomFieldOption option = (CustomFieldOption) container;
      container = options.sourceOf(option);
    }
    if (container instanceof SimpleValueField) {
      SimpleValueField field = (SimpleValueField) container;
      container = field.getName().getTarget();
    }
    if (container instanceof MessageField) {
      anEnum = modelFinder.enumTypeOf((MessageField) container);
    }
    return createScope(literalDescriptions.literalsOf(anEnum));
  }

  @SuppressWarnings("unused") public IScope scope_OptionSource_target(OptionSource source, EReference r) {
    EObject c = source.eContainer();
    if (c instanceof NativeOption) {
      NativeOption option = (NativeOption) c;
      return createScope(nativeOptionDescriptions.sources(option));
    }
    if (c instanceof NativeFieldOption) {
      NativeFieldOption option = (NativeFieldOption) c;
      return createScope(nativeOptionDescriptions.sources(option));
    }
    if (c instanceof CustomOption) {
      CustomOption option = (CustomOption) c;
      return createScope(allPossibleSourcesOf(option));
    }
    if (c instanceof CustomFieldOption) {
      CustomFieldOption option = (CustomFieldOption) c;
      return createScope(allPossibleSourcesOf(option));
    }
    Set<IEObjectDescription> descriptions = emptySet();
    return createScope(descriptions);
  }

  @Override public Collection<IEObjectDescription> allPossibleSourcesOf(CustomOption option) {
    OptionType optionType = typeOf(option);
    Collection<IEObjectDescription> descriptions = emptySet();
    if (optionType != null) {
      descriptions = astWalker.traverseAst(option, customOptionScopeFinder, optionType);
    }
    return descriptions;
  }

  @Override public Collection<IEObjectDescription> allPossibleSourcesOf(CustomFieldOption option) {
    OptionType optionType = typeOf(option);
    Collection<IEObjectDescription> descriptions = emptySet();
    if (optionType != null) {
      descriptions = astWalker.traverseAst(option, customOptionScopeFinder, optionType);
    }
    return descriptions;
  }

  @SuppressWarnings("unused") public IScope scope_OptionField_target(OptionField field, EReference r) {
    return createScope(allPossibleSourcesOf(field));
  }

  private Collection<IEObjectDescription> allPossibleSourcesOf(OptionField field) {
    if (field == null) {
      return emptySet();
    }
    EObject container = field.eContainer();
    if (container instanceof CustomOption) {
      CustomOption option = (CustomOption) container;
      if (field instanceof MessageOptionField) { return findSources(option, (MessageOptionField) field); }
      return findSources(option, (ExtensionOptionField) field);
    }
    if (container instanceof CustomFieldOption) {
      CustomFieldOption option = (CustomFieldOption) container;
      if (field instanceof MessageOptionField) { return findSources(option, (MessageOptionField) field); }
      return findSources(option, (ExtensionOptionField) field);
    }
    return emptySet();
  }

  @Override public Collection<IEObjectDescription> allPossibleNormalFieldsOf(CustomOption option) {
    return findSources(option, (MessageOptionField) null);
  }

  @Override public Collection<IEObjectDescription> allPossibleNormalFieldsOf(CustomFieldOption option) {
    return findSources(option, (MessageOptionField) null);
  }

  @Override public Collection<IEObjectDescription> allPossibleExtensionFieldsOf(CustomOption option) {
    return findSources(option, (ExtensionOptionField) null);
  }

  @Override public Collection<IEObjectDescription> allPossibleExtensionFieldsOf(CustomFieldOption option) {
    return findSources(option, (ExtensionOptionField) null);
  }

  private Collection<IEObjectDescription> findSources(CustomOption option, MessageOptionField field) {
    return customOptionFieldScopeFinder.findScope(option, field);
  }

  private Collection<IEObjectDescription> findSources(CustomOption option, ExtensionOptionField field) {
    return customOptionFieldScopeFinder.findScope(option, field);
  }

  private Collection<IEObjectDescription> findSources(CustomFieldOption option, MessageOptionField field) {
    return customOptionFieldScopeFinder.findScope(option, field);
  }

  private Collection<IEObjectDescription> findSources(CustomFieldOption option, ExtensionOptionField field) {
    return customOptionFieldScopeFinder.findScope(option, field);
  }

  @SuppressWarnings("unused") public IScope scope_FieldName_target(FieldName name, EReference r) {
    return createScope(findSources(name));
  }

  private Collection<IEObjectDescription> findSources(FieldName name) {
    ComplexValue value = container(name);
    if (value == null) {
      return emptySet();
    }
    if (name instanceof NormalFieldName) { return allPossibleNamesOfNormalFieldsOf(value); }
    return allPossibleNamesOfExtensionFieldsOf(value);
  }

  private ComplexValue container(FieldName name) {
    EObject container = name;
    while (container != null) {
      if (container instanceof ComplexValue) { return (ComplexValue) container; }
      container = container.eContainer();
    }
    return null;
  }

  @Override public Collection<IEObjectDescription> allPossibleNamesOfNormalFieldsOf(ComplexValue value) {
    return fieldNotationScopeFinder.sourceOfNormalFieldNamesOf(value);
  }

  @Override public Collection<IEObjectDescription> allPossibleNamesOfExtensionFieldsOf(ComplexValue value) {
    return fieldNotationScopeFinder.sourceOfExtensionFieldNamesOf(value);
  }

  private static IScope createScope(Iterable<IEObjectDescription> descriptions) {
    return new SimpleScope(descriptions, DO_NOT_IGNORE_CASE);
  }
}
