package org.jetbrains.plugins.gradle.remote.impl;

import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.project.LibraryData;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.intellij.openapi.externalSystem.model.project.LibraryPathType;

import java.io.File;
import java.util.*;

/**
 * Encapsulates logic of checking if particular collection of gradle libraries contains libraries with the same names and
 * tries to diversify them in the case of the positive answer.
 * <p/>
 * Thread-safe.
 * 
 * @author Denis Zhdanov
 * @since 10/19/11 2:04 PM
 */
public class GradleLibraryNamesMixer {

  /**
   * Holds mappings like <code>('file name'; boolean)</code> where <code>'file name'</code> defines 'too common' file/dir
   * name that should not be used during library name generation. Boolean flag indicates if 'common file name' may be used
   * if 'non-common' files are the same.
   * <p/>
   * Example: consider the following file system tree:
   * <pre>
   *   module
   *     |_src
   *        |_main
   *        |  |_resources
   *        |
   *        |_test
   *           |_resources
   * </pre>
   * Let's say we have two libraries where one of them points to <code>'src/main/resources'</code> and another one
   * to <code>'src/test/resources'</code>. We want to generate names <code>'module-resources'</code> and
   * <code>'module-test-resources'</code> respectively because <code>'test'</code> entry at the current collection is
   * stored with <code>'true'</code> flag.
   */
  private static final Map<String, Boolean> NON_UNIQUE_PATH_ENTRIES = new HashMap<String, Boolean>();
  static {
    NON_UNIQUE_PATH_ENTRIES.put("src", false);
    NON_UNIQUE_PATH_ENTRIES.put("main", false);
    NON_UNIQUE_PATH_ENTRIES.put("test", true);
    NON_UNIQUE_PATH_ENTRIES.put("resources", false);
    NON_UNIQUE_PATH_ENTRIES.put("java", false);
    NON_UNIQUE_PATH_ENTRIES.put("groovy", false);
  }
  private static final char NAME_SEPARATOR = '-';

  /**
   * Tries to ensure that given libraries have distinct names, i.e. traverses all of them and tries to generate
   * unique name for those with equal names.
   * 
   * @param libraries  libraries to process
   */
  @SuppressWarnings("MethodMayBeStatic")
  public void mixNames(@NotNull Collection<DataNode<LibraryData>> libraries) {
    if (libraries.isEmpty()) {
      return;
    }
    Map<String, Wrapped> names = ContainerUtilRt.newHashMap();
    List<Wrapped> data = ContainerUtilRt.newArrayList();
    for (DataNode<LibraryData> library : libraries) {
      Wrapped wrapped = new Wrapped(library.getData());
      data.add(wrapped);
    }
    boolean mixed = false;
    while (!mixed) {
      mixed = doMixNames(data, names);
    }
  }

  /**
   * Does the same as {@link #mixNames(Collection)} but uses given <code>('library name; wrapped library'}</code> mappings cache.
   * 
   * @param libraries  libraries to process
   * @param cache      cache to use
   * @return           <code>true</code> if all of the given libraries have distinct names now; <code>false</code> otherwise
   */
  private static boolean doMixNames(@NotNull Collection<Wrapped> libraries, @NotNull Map<String, Wrapped> cache) {
    cache.clear();
    for (Wrapped current : libraries) {
      Wrapped previous = cache.remove(current.library.getExternalName());
      if (previous == null) {
        cache.put(current.library.getExternalName(), current);
      }
      else {
        mixNames(current, previous);
        return current.library.getExternalName().equals(previous.library.getExternalName()); // Stop processing if it's not possible to generate
      }
    }
    return true;
  }

  /**
   * Tries to generate distinct names for the given wrapped libraries (assuming that they have equal names at the moment).
   * 
   * @param wrapped1  one of the libraries with equal names
   * @param wrapped2  another library which name is equal to the name of the given one
   */
  @SuppressWarnings("AssignmentToForLoopParameter")
  private static void mixNames(@NotNull Wrapped wrapped1, @NotNull Wrapped wrapped2) {
    if (!wrapped1.prepare() || !wrapped2.prepare()) {
      return;
    }
    String wrapped1AltText = null;
    String wrapped2AltText = null;
    
    for (File file1 = wrapped1.currentFile, file2 = wrapped2.currentFile;
         file1 != null && file2 != null;
         file1 = file1.getParentFile(), file2 = file2.getParentFile())
    {
      while (file1 != null && !StringUtil.isEmpty(file1.getName()) && NON_UNIQUE_PATH_ENTRIES.containsKey(file1.getName())) {
        if (NON_UNIQUE_PATH_ENTRIES.get(file1.getName())) {
          if (StringUtil.isEmpty(wrapped1AltText)) {
            wrapped1AltText = file1.getName();
          }
          else {
            wrapped1AltText += NAME_SEPARATOR + file1.getName();
          }
        }
        file1 = file1.getParentFile();
      }
      while (file2 != null && !StringUtil.isEmpty(file2.getName()) && NON_UNIQUE_PATH_ENTRIES.containsKey(file2.getName())) {
        if (NON_UNIQUE_PATH_ENTRIES.get(file2.getName())) {
          if (StringUtil.isEmpty(wrapped2AltText)) {
            wrapped2AltText = file2.getName();
          }
          else {
            wrapped2AltText += NAME_SEPARATOR + file2.getName();
          }
        }
        file2 = file2.getParentFile();
      }
      
      if (file1 == null) {
        wrapped1.nextFile();
      }
      else if (!wrapped1.library.getExternalName().startsWith(file1.getName())) {
        wrapped1.library.setExternalName(file1.getName() + NAME_SEPARATOR + wrapped1.library.getExternalName());
      }
      if (file2 == null) {
        wrapped2.nextFile();
      }
      else if (!wrapped2.library.getExternalName().startsWith(file2.getName())) {
        wrapped2.library.setExternalName(file2.getName() + NAME_SEPARATOR + wrapped2.library.getExternalName());
      }

      if (wrapped1.library.getExternalName().equals(wrapped2.library.getExternalName())) {
        if (wrapped1AltText != null) {
          diversifyName(wrapped1AltText, wrapped1, file1);
          return;
        }
        else if (wrapped2AltText != null) {
          diversifyName(wrapped2AltText, wrapped2, file1);
          return;
        }
      }
      else {
        return;
      }

      if (file1 == null || file2 == null) {
        return;
      }
    }
  }

  @SuppressWarnings("ConstantConditions")
  private static void diversifyName(@NotNull String changeText, @NotNull Wrapped wrapped, @Nullable File file) {
    String name = wrapped.library.getExternalName();
    int i = file == null ? - 1 : name.indexOf(file.getName());
    final String newName;
    if (i >= 0) {
      newName = name.substring(0, i + file.getName().length()) + NAME_SEPARATOR + changeText + name.substring(i + file.getName().length());
    }
    else {
      newName = changeText + NAME_SEPARATOR + name;
    }
    wrapped.library.setExternalName(newName);
  }

  /**
   * Wraps target library and hold auxiliary information required for the processing.
   */
  private static class Wrapped {
    /** Holds list of files that may be used for name generation. */
    public final Set<File> files = new HashSet<File>();
    /** File that was used for the current name generation. */
    public File        currentFile;
    /** Target library. */
    public LibraryData library;

    Wrapped(@NotNull LibraryData library) {
      this.library = library;
      for (LibraryPathType pathType : LibraryPathType.values()) {
        for (String path : library.getPaths(pathType)) {
          files.add(new File(path));
        }
      }
    }

    public boolean prepare() {
      if (currentFile != null) {
        return true;
      }
      return nextFile();
    }

    public boolean nextFile() {
      if (files.isEmpty()) {
        return false;
      }
      Iterator<File> iterator = files.iterator();
      currentFile = iterator.next();
      iterator.remove();
      return true;
    }
  }
}
