/*
 * Copyright 2000-2012 JetBrains s.r.o.
 *
 * 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.intellij.openapi.roots.impl;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.NotNullFunction;
import com.intellij.util.Processor;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
 * @author nik
 */
abstract class OrderEnumeratorBase extends OrderEnumerator implements OrderEnumeratorSettings {
  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.OrderEnumeratorBase");
  private boolean myProductionOnly;
  private boolean myCompileOnly;
  private boolean myRuntimeOnly;
  private boolean myWithoutJdk;
  private boolean myWithoutLibraries;
  protected boolean myWithoutDepModules;
  private boolean myWithoutModuleSourceEntries;
  protected boolean myRecursively;
  protected boolean myRecursivelyExportedOnly;
  private boolean myExportedOnly;
  private Condition<OrderEntry> myCondition;
  private final List<OrderEnumerationHandler> myCustomHandlers;
  protected RootModelProvider myModulesProvider;
  private final OrderRootsCache myCache;

  public OrderEnumeratorBase(@Nullable Module module, @NotNull Project project, @Nullable OrderRootsCache cache) {
    myCache = cache;
    List<OrderEnumerationHandler> customHandlers = null;
    for (OrderEnumerationHandler.Factory handlerFactory : OrderEnumerationHandler.EP_NAME.getExtensions()) {
      if (handlerFactory.isApplicable(project) && (module == null || handlerFactory.isApplicable(module))) {
        if (customHandlers == null) {
          customHandlers = new SmartList<OrderEnumerationHandler>();
        }
        customHandlers.add(handlerFactory.createHandler(module));
      }
    }
    this.myCustomHandlers = customHandlers == null ? Collections.<OrderEnumerationHandler>emptyList() : customHandlers;
  }

  @Override
  public OrderEnumerator productionOnly() {
    myProductionOnly = true;
    return this;
  }

  @Override
  public OrderEnumerator compileOnly() {
    myCompileOnly = true;
    return this;
  }

  @Override
  public OrderEnumerator runtimeOnly() {
    myRuntimeOnly = true;
    return this;
  }

  @Override
  public OrderEnumerator withoutSdk() {
    myWithoutJdk = true;
    return this;
  }

  @Override
  public OrderEnumerator withoutLibraries() {
    myWithoutLibraries = true;
    return this;
  }

  @Override
  public OrderEnumerator withoutDepModules() {
    myWithoutDepModules = true;
    return this;
  }

  @Override
  public OrderEnumerator withoutModuleSourceEntries() {
    myWithoutModuleSourceEntries = true;
    return this;
  }

  @Override
  public OrderEnumerator recursively() {
    myRecursively = true;
    return this;
  }

  @Override
  public OrderEnumerator exportedOnly() {
    if (myRecursively) {
      myRecursivelyExportedOnly = true;
    }
    else {
      myExportedOnly = true;
    }
    return this;
  }

  @Override
  public OrderEnumerator satisfying(Condition<OrderEntry> condition) {
    myCondition = condition;
    return this;
  }

  @Override
  public OrderEnumerator using(@NotNull RootModelProvider provider) {
    myModulesProvider = provider;
    return this;
  }

  @Override
  public OrderRootsEnumerator classes() {
    return new OrderRootsEnumeratorImpl(this, OrderRootType.CLASSES);
  }

  @Override
  public OrderRootsEnumerator sources() {
    return new OrderRootsEnumeratorImpl(this, OrderRootType.SOURCES);
  }

  @Override
  public OrderRootsEnumerator roots(@NotNull OrderRootType rootType) {
    return new OrderRootsEnumeratorImpl(this, rootType);
  }

  @Override
  public OrderRootsEnumerator roots(@NotNull NotNullFunction<OrderEntry, OrderRootType> rootTypeProvider) {
    return new OrderRootsEnumeratorImpl(this, rootTypeProvider);
  }

  ModuleRootModel getRootModel(Module module) {
    if (myModulesProvider != null) {
      return myModulesProvider.getRootModel(module);
    }
    return ModuleRootManager.getInstance(module);
  }

  public OrderRootsCache getCache() {
    LOG.assertTrue(myCache != null, "Caching is not supported for ModifiableRootModel");
    LOG.assertTrue(myCondition == null, "Caching not supported for OrderEnumerator with 'satisfying(Condition)' option");
    LOG.assertTrue(myModulesProvider == null, "Caching not supported for OrderEnumerator with 'using(ModulesProvider)' option");
    return myCache;
  }

  public int getFlags() {
    int flags = 0;
    if (myProductionOnly) flags |= 1;
    flags <<= 1;
    if (myCompileOnly) flags |= 1;
    flags <<= 1;
    if (myRuntimeOnly) flags |= 1;
    flags <<= 1;
    if (myWithoutJdk) flags |= 1;
    flags <<= 1;
    if (myWithoutLibraries) flags |= 1;
    flags <<= 1;
    if (myWithoutDepModules) flags |= 1;
    flags <<= 1;
    if (myWithoutModuleSourceEntries) flags |= 1;
    flags <<= 1;
    if (myRecursively) flags |= 1;
    flags <<= 1;
    if (myRecursivelyExportedOnly) flags |= 1;
    flags <<= 1;
    if (myExportedOnly) flags |= 1;
    return flags;
  }

  protected void processEntries(final ModuleRootModel rootModel,
                                Processor<OrderEntry> processor,
                                Set<Module> processed, boolean firstLevel) {
    if (processed != null && !processed.add(rootModel.getModule())) return;

    for (OrderEntry entry : rootModel.getOrderEntries()) {
      if (myCondition != null && !myCondition.value(entry)) continue;

      if (myWithoutJdk && entry instanceof JdkOrderEntry) continue;
      if (myWithoutLibraries && entry instanceof LibraryOrderEntry) continue;
      if (myWithoutDepModules) {
        if (!myRecursively && entry instanceof ModuleOrderEntry) continue;
        if (entry instanceof ModuleSourceOrderEntry && !isRootModuleModel(((ModuleSourceOrderEntry)entry).getRootModel())) continue;
      }
      if (myWithoutModuleSourceEntries && entry instanceof ModuleSourceOrderEntry) continue;

      OrderEnumerationHandler.AddDependencyType shouldAdd = OrderEnumerationHandler.AddDependencyType.DEFAULT;
      for (OrderEnumerationHandler handler : myCustomHandlers) {
        shouldAdd = handler.shouldAddDependency(entry, this);
        if (shouldAdd != OrderEnumerationHandler.AddDependencyType.DEFAULT) break;
      }
      if (shouldAdd == OrderEnumerationHandler.AddDependencyType.DO_NOT_ADD) continue;

      boolean exported = !(entry instanceof JdkOrderEntry);

      if (entry instanceof ExportableOrderEntry) {
        ExportableOrderEntry exportableEntry = (ExportableOrderEntry)entry;
        if (shouldAdd == OrderEnumerationHandler.AddDependencyType.DEFAULT) {
          final DependencyScope scope = exportableEntry.getScope();
          boolean forTestCompile = scope.isForTestCompile() || scope == DependencyScope.RUNTIME && shouldAddRuntimeDependenciesToTestCompilationClasspath();
          if (myCompileOnly && !scope.isForProductionCompile() && !forTestCompile) continue;
          if (myRuntimeOnly && !scope.isForProductionRuntime() && !scope.isForTestRuntime()) continue;
          if (myProductionOnly) {
            if (!scope.isForProductionCompile() && !scope.isForProductionRuntime()
                || myCompileOnly && !scope.isForProductionCompile()
                || myRuntimeOnly && !scope.isForProductionRuntime()) {
              continue;
            }
          }
        }
        exported = exportableEntry.isExported();
      }
      if (!exported) {
        if (myExportedOnly) continue;
        if (myRecursivelyExportedOnly && !firstLevel) continue;
      }

      if (myRecursively && entry instanceof ModuleOrderEntry) {
        ModuleOrderEntry moduleOrderEntry = (ModuleOrderEntry)entry;
        final Module module = moduleOrderEntry.getModule();
        if (module != null && shouldProcessRecursively()) {
          processEntries(getRootModel(module), processor, processed, false);
          continue;
        }
      }

      if (myWithoutDepModules && entry instanceof ModuleOrderEntry) continue;
      if (!processor.process(entry)) {
        return;
      }
    }
  }

  private boolean shouldAddRuntimeDependenciesToTestCompilationClasspath() {
    for (OrderEnumerationHandler handler : myCustomHandlers) {
      if (handler.shouldAddRuntimeDependenciesToTestCompilationClasspath()) {
        return true;
      }
    }
    return false;
  }

  private boolean shouldProcessRecursively() {
    for (OrderEnumerationHandler handler : myCustomHandlers) {
      if (!handler.shouldProcessDependenciesRecursively()) {
        return false;
      }
    }
    return true;
  }

  @Override
  public void forEachLibrary(@NotNull final Processor<Library> processor) {
    forEach(new Processor<OrderEntry>() {
      @Override
      public boolean process(OrderEntry orderEntry) {
        if (orderEntry instanceof LibraryOrderEntry) {
          final Library library = ((LibraryOrderEntry)orderEntry).getLibrary();
          if (library != null) {
            return processor.process(library);
          }
        }
        return true;
      }
    });
  }

  @Override
  public void forEachModule(@NotNull final Processor<Module> processor) {
    forEach(new Processor<OrderEntry>() {
      @Override
      public boolean process(OrderEntry orderEntry) {
        if (myRecursively && orderEntry instanceof ModuleSourceOrderEntry) {
          final Module module = ((ModuleSourceOrderEntry)orderEntry).getRootModel().getModule();
          return processor.process(module);
        }
        else if (orderEntry instanceof ModuleOrderEntry && (!myRecursively || !shouldProcessRecursively())) {
          final Module module = ((ModuleOrderEntry)orderEntry).getModule();
          if (module != null) {
            return processor.process(module);
          }
        }
        return true;
      }
    });
  }

  @Override
  public <R> R process(@NotNull final RootPolicy<R> policy, final R initialValue) {
    final OrderEntryProcessor<R> processor = new OrderEntryProcessor<R>(policy, initialValue);
    forEach(processor);
    return processor.myValue;
  }

  boolean shouldIncludeTestsFromDependentModulesToTestClasspath() {
    for (OrderEnumerationHandler handler : myCustomHandlers) {
      if (!handler.shouldIncludeTestsFromDependentModulesToTestClasspath()) {
        return false;
      }
    }
    return true;
  }

  boolean addCustomRootsForLibrary(OrderEntry forOrderEntry, OrderRootType type, Collection<VirtualFile> result) {
    for (OrderEnumerationHandler handler : myCustomHandlers) {
      final List<String> urls = new ArrayList<String>();
      final boolean added =
        handler.addCustomRootsForLibrary(forOrderEntry, type, urls);
      for (String url : urls) {
        ContainerUtil.addIfNotNull(VirtualFileManager.getInstance().findFileByUrl(url), result);
      }
      if (added) {
        return true;
      }
    }
    return false;
  }

  boolean addCustomRootUrlsForLibrary(OrderEntry forOrderEntry, OrderRootType type, Collection<String> result) {
    for (OrderEnumerationHandler handler : myCustomHandlers) {
      final List<String> urls = new ArrayList<String>();
      final boolean added =
        handler.addCustomRootsForLibrary(forOrderEntry, type, urls);
      result.addAll(urls);
      if (added) {
        return true;
      }
    }
    return false;
  }

  boolean addCustomRootsForModule(OrderRootType type,
                                  ModuleRootModel rootModel,
                                  Collection<VirtualFile> result,
                                  boolean includeProduction,
                                  boolean includeTests) {
    for (OrderEnumerationHandler handler : myCustomHandlers) {
      final List<String> urls = new ArrayList<String>();
      final boolean added = handler.addCustomModuleRoots(type, rootModel, urls, includeProduction, includeTests);
      for (String url : urls) {
        ContainerUtil.addIfNotNull(VirtualFileManager.getInstance().findFileByUrl(url), result);
      }

      if (added) return true;
    }
    return false;
  }

  boolean addCustomRootUrlsForModule(OrderRootType type,
                                     ModuleRootModel rootModel,
                                     Collection<String> result,
                                     boolean includeProduction,
                                     boolean includeTests) {
    for (OrderEnumerationHandler handler : myCustomHandlers) {
      final List<String> urls = new ArrayList<String>();
      final boolean added = handler.addCustomModuleRoots(type, rootModel, urls, includeProduction, includeTests);
      result.addAll(urls);

      if (added) return true;
    }
    return false;
  }

  @Override
  public boolean isRuntimeOnly() {
    return myRuntimeOnly;
  }

  @Override
  public boolean isCompileOnly() {
    return myCompileOnly;
  }

  @Override
  public boolean isProductionOnly() {
    return myProductionOnly;
  }

  public boolean isRootModuleModel(@NotNull ModuleRootModel rootModel) {
    return false;
  }

  /**
   * Runs processor on each module that this enumerator was created on.
   *
   * @param processor processor
   */
  public abstract void processRootModules(@NotNull Processor<Module> processor);

  private class OrderEntryProcessor<R> implements Processor<OrderEntry> {
    private R myValue;
    private final RootPolicy<R> myPolicy;

    public OrderEntryProcessor(RootPolicy<R> policy, R initialValue) {
      myPolicy = policy;
      myValue = initialValue;
    }

    @Override
    public boolean process(OrderEntry orderEntry) {
      myValue = orderEntry.accept(myPolicy, myValue);
      return true;
    }
  }
}
