/*
 * Copyright 2000-2015 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 org.jetbrains.idea.eclipse;

import com.intellij.openapi.components.ExpandMacroToPathMap;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.*;
import java.util.*;
import java.util.jar.Manifest;
import java.util.regex.PatternSyntaxException;

public abstract class AbstractEclipseClasspathReader<T> {
  protected final String myRootPath;
  @Nullable protected final List<String> myCurrentRoots;
  @Nullable protected final Set<String> myModuleNames;

  public AbstractEclipseClasspathReader(@NotNull String rootPath, @Nullable List<String> currentRoots, @Nullable Set<String> moduleNames) {
    myRootPath = FileUtil.toSystemIndependentName(rootPath);
    myCurrentRoots = currentRoots;
    myModuleNames = moduleNames;
  }

  protected abstract String prepareValidUrlInsideJar(String url);

  protected abstract void addNamedLibrary(T rootModel,
                                          Collection<? super String> unknownLibraries,
                                          boolean exported,
                                          String name,
                                          boolean applicationLevel);

  protected abstract void addInvalidModuleEntry(T rootModel, boolean exported, String moduleName);

  protected abstract void setUpModuleJdk(T rootModel,
                                         Collection<? super String> unknownJdks,
                                         EclipseModuleManager eclipseModuleManager,
                                         String jdkName);

  public abstract void setupOutput(T rootModel, String path);

  protected abstract void addSourceFolder(T rootModel, String srcUrl, boolean testFolder);

  protected abstract void addSourceFolderToCurrentContentRoot(T rootModel, String srcUrl, boolean testFolder);

  protected abstract void addJUnitDefaultLib(T rootModel, String junitName, ExpandMacroToPathMap macroMap);

  protected abstract void addModuleLibrary(T rootModel,
                                           Element element,
                                           boolean exported,
                                           String libName,
                                           String url,
                                           String srcUrl, String nativeRoot, ExpandMacroToPathMap macroMap);

  protected abstract String expandEclipsePath2Url(T rootModel, String path);

  protected abstract Set<String> getDefinedCons();

  protected abstract int rearrange(T rootModel);

  protected void readClasspathEntry(T rootModel,
                                    final Collection<? super String> unknownLibraries,
                                    Collection<? super String> unknownJdks,
                                    Set<? super String> refsToModules,
                                    final String testPattern,
                                    Element element, int index,
                                    @Nullable EclipseModuleManager eclipseModuleManager,
                                    final ExpandMacroToPathMap macroMap,
                                    final Set<? super String> libs) throws ConversionException {
    String kind = element.getAttributeValue(EclipseXml.KIND_ATTR);
    if (kind == null) {
      throw new ConversionException("Missing classpathentry/@kind");
    }

    String path = element.getAttributeValue(EclipseXml.PATH_ATTR);
    if (path == null) {
      throw new ConversionException("Missing classpathentry/@path");
    }

    final boolean exported = EclipseXml.TRUE_VALUE.equals(element.getAttributeValue(EclipseXml.EXPORTED_ATTR));

    if (kind.equals(EclipseXml.SRC_KIND)) {
      if (path.startsWith("/")) {
        final String moduleName = path.substring(1);
        refsToModules.add(moduleName);
        addInvalidModuleEntry(rootModel, exported, moduleName);
      }
      else {
        String srcUrl = pathToUrl(getPathRelativeToRoot(path));
        boolean isTestFolder;
        try {
          isTestFolder = !StringUtil.isEmpty(testPattern) && path.matches(testPattern);
        }
        catch (PatternSyntaxException e) {
          isTestFolder = false;
        }
        String linked = expandLinkedResourcesPath(macroMap, path);
        if (linked == null) {
          addSourceFolderToCurrentContentRoot(rootModel, srcUrl, isTestFolder);
        }
        else {
          srcUrl = prepareValidUrlInsideJar(pathToUrl(linked));
          if (eclipseModuleManager != null) {
            eclipseModuleManager.registerEclipseLinkedSrcVarPath(srcUrl, path);
          }
          addSourceFolder(rootModel, srcUrl, isTestFolder);
        }

        if (eclipseModuleManager != null) {
          eclipseModuleManager.setExpectedModuleSourcePlace(rearrange(rootModel));
          eclipseModuleManager.registerSrcPlace(srcUrl, index);
        }
      }
    }
    else if (kind.equals(EclipseXml.OUTPUT_KIND)) {
      String output = getPathRelativeToRoot(path);
      String linked = expandLinkedResourcesPath(macroMap, path);
      if (linked != null) {
        output = linked;
        if (eclipseModuleManager != null) {
          eclipseModuleManager.registerEclipseLinkedVarPath(pathToUrl(output), path);
        }
      }
      setupOutput(rootModel, output);
    }
    else if (kind.equals(EclipseXml.LIB_KIND)) {
      String linked = expandLinkedResourcesPath(macroMap, path);
      String url;
      if (linked != null) {
        url = prepareValidUrlInsideJar(pathToUrl(linked));
        if (eclipseModuleManager != null) {
          eclipseModuleManager.registerEclipseLinkedVarPath(url, path);
        }
      }
      else {
        url = expandEclipsePath2Url(rootModel, path);
      }

      if (eclipseModuleManager != null) {
        eclipseModuleManager.registerEclipseLibUrl(url);
      }

      final String sourcePath = element.getAttributeValue(EclipseXml.SOURCEPATH_ATTR);
      String srcUrl = null;
      if (sourcePath != null) {
        final String linkedSrc = expandLinkedResourcesPath(macroMap, sourcePath);
        if (linkedSrc != null) {
          srcUrl = prepareValidUrlInsideJar(pathToUrl(linkedSrc));
          if (eclipseModuleManager != null) {
            eclipseModuleManager.registerEclipseLinkedSrcVarPath(srcUrl, sourcePath);
          }
        }
        else {
          srcUrl = expandEclipsePath2Url(rootModel, sourcePath);
        }
      }

      String nativeRoot = getNativeLibraryRoot(element);
      if (nativeRoot != null) {
        nativeRoot = expandEclipsePath2Url(rootModel, nativeRoot);
      }

      addModuleLibrary(rootModel, element, exported, getPresentableName(path, libs), url, srcUrl, nativeRoot, macroMap);
    }
    else if (kind.equals(EclipseXml.VAR_KIND)) {
      int slash = path.indexOf("/");
      if (slash == 0) {
        throw new ConversionException("Incorrect 'classpathentry/var@path' format");
      }

      final String libName = getPresentableName(path, libs);

      String url = eclipseVariabledPath2Url(macroMap, path, 0);
      if (eclipseModuleManager != null) {
        eclipseModuleManager.registerEclipseVariablePath(url, path);
      }
      final String srcPathAttr = element.getAttributeValue(EclipseXml.SOURCEPATH_ATTR);
      String srcUrl = null;
      if (srcPathAttr != null) {
        srcUrl = eclipseVariabledPath2Url(macroMap, srcPathAttr, srcVarStart(srcPathAttr));
        if (eclipseModuleManager != null) {
          eclipseModuleManager.registerEclipseSrcVariablePath(srcUrl, srcPathAttr);
        }
      }
      String nativeRoot = getNativeLibraryRoot(element);
      if (nativeRoot != null) {
        nativeRoot = expandEclipsePath2Url(rootModel, nativeRoot);
      }
      addModuleLibrary(rootModel, element, exported, libName, url, srcUrl, nativeRoot, macroMap);
    }
    else if (kind.equals(EclipseXml.CON_KIND)) {
      if (path.equals(EclipseXml.ECLIPSE_PLATFORM)) {
        readRequiredBundles(rootModel, refsToModules);
        addNamedLibrary(rootModel, unknownLibraries, exported, IdeaXml.ECLIPSE_LIBRARY, true);
      }
      else if (path.startsWith(EclipseXml.JRE_CONTAINER)) {

        final String jdkName = getLastPathComponent(path);
        setUpModuleJdk(rootModel, unknownJdks, eclipseModuleManager, jdkName);
      }
      else if (path.startsWith(EclipseXml.USER_LIBRARY)) {
        addNamedLibrary(rootModel, unknownLibraries, exported, getPresentableName(path), false);
      }
      else if (path.startsWith(EclipseXml.JUNIT_CONTAINER)) {
        final String junitName = IdeaXml.JUNIT + getPresentableName(path);
        addJUnitDefaultLib(rootModel, junitName, macroMap);
      }
      else {
        Set<String> registeredCons = getDefinedCons();
        if (registeredCons.contains(path)) {
          if (eclipseModuleManager != null) {
            eclipseModuleManager.registerCon(path);
            eclipseModuleManager.registerSrcPlace(path, index);
          }
        }
        else {
          if (eclipseModuleManager != null) {
            eclipseModuleManager.registerUnknownCons(path);
          }
          addNamedLibrary(rootModel, new ArrayList<>(), exported, path, true);
        }
      }
    }
    else {
      throw new ConversionException("Unknown classpathentry/@kind: " + kind);
    }
  }

  private String getPathRelativeToRoot(String path) {
    return path.isEmpty() ? myRootPath : (myRootPath + "/" + path);
  }

  private static String getNativeLibraryRoot(Element element) {
    final Element attributes = element.getChild(EclipseXml.ATTRIBUTES_TAG);
    if (attributes != null) {
      for (Element attributeElement : attributes.getChildren(EclipseXml.ATTRIBUTE_TAG)) {
        if (EclipseXml.DLL_LINK.equals(attributeElement.getAttributeValue(EclipseXml.NAME_ATTR))) {
          return attributeElement.getAttributeValue(EclipseXml.VALUE_ATTR);
        }
      }
    }
    return null;
  }

  protected static int srcVarStart(String srcPath) {
    return srcPath.startsWith("/") ? 1 : 0;
  }

  @NotNull
  protected static String getPresentableName(@NotNull String path) {
    return getPresentableName(path, null);
  }

  @NotNull
  protected static String getPresentableName(@NotNull String path, Set<? super String> names) {
    String pathComponent = getLastPathComponent(path);
    if (pathComponent != null && names != null && !names.add(pathComponent)) {
      return path;
    }
    else {
      return pathComponent == null ? path : pathComponent;
    }
  }

  @Nullable
  public static String getLastPathComponent(final String path) {
    final int idx = path.lastIndexOf('/');
    return idx < 0 || idx == path.length() - 1 ? null : path.substring(idx + 1);
  }

  @NotNull
  protected static String getVariableRelatedPath(@NotNull String var, String path) {
    return "$" + var + "$" + (path == null ? "" : "/" + path);
  }

  @NotNull
  protected static String pathToUrl(@NotNull String path) {
    return "file://" + FileUtil.toSystemIndependentName(path);
  }

  protected static EPathVariable createEPathVariable(String pathAttr, int varStart) {
    int slash = pathAttr.indexOf("/", varStart);
    if (slash > 0) {
      return new EPathVariable(pathAttr.substring(varStart, slash), pathAttr.substring(slash + 1));
    }
    else {
      return new EPathVariable(pathAttr.substring(varStart), null);
    }
  }

  @SuppressWarnings("SpellCheckingInspection")
  protected String eclipseVariabledPath2Url(ExpandMacroToPathMap pathMap, String path, int varStart) {
    EPathVariable var = createEPathVariable(path, varStart);
    return prepareValidUrlInsideJar(pathMap.substitute(pathToUrl(getVariableRelatedPath(var.myVariable, var.myRelatedPath)), SystemInfo.isFileSystemCaseSensitive));
  }

  @Nullable
  protected String expandLinkedResourcesPath(final ExpandMacroToPathMap macroMap,
                                             final String path) {
    final EclipseProjectFinder.LinkedResource linkedResource = EclipseProjectFinder.findLinkedResource(myRootPath, path);
    if (linkedResource != null) {
      if (linkedResource.containsPathVariable()) {
        final String toPathVariableFormat =
          getVariableRelatedPath(linkedResource.getVariableName(), linkedResource.getRelativeToVariablePath());
        return macroMap.substitute(toPathVariableFormat, SystemInfo.isFileSystemCaseSensitive);
      }
      return linkedResource.getLocation();
    }
    return null;
  }


  protected void readRequiredBundles(T rootModel, Set<? super String> refsToModules) throws ConversionException {
    if (myModuleNames == null) {
      return;
    }

    final File manifestFile = new File(myRootPath, "META-INF/MANIFEST.MF");
    if (!manifestFile.exists()) {
      return;
    }

    InputStream in = null;
    try {
      in = new BufferedInputStream(new FileInputStream(manifestFile));
      final Manifest manifest = new Manifest(in);
      final String attributes = manifest.getMainAttributes().getValue("Require-Bundle");
      if (!StringUtil.isEmpty(attributes)) {
        final StringTokenizer tokenizer = new StringTokenizer(attributes, ",");
        while (tokenizer.hasMoreTokens()) {
          String bundle = tokenizer.nextToken().trim();
          if (!bundle.isEmpty()) {
            final int constraintIndex = bundle.indexOf(';');
            if (constraintIndex != -1) {
              bundle = bundle.substring(0, constraintIndex).trim();
            }

            if (myModuleNames.contains(bundle)) {
              refsToModules.add(bundle);
              addInvalidModuleEntry(rootModel, false, bundle);
            }
          }
        }
      }
    }
    catch (IOException e) {
      throw new ConversionException(e.getMessage());
    }
    finally {
      if (in != null) {
        try {
          in.close();
        }
        catch (IOException ignored) {
        }
      }
    }
  }

  protected static class EPathVariable {
    @NotNull
    private final String myVariable;
    private final String myRelatedPath;

    protected EPathVariable(@NotNull String variable, final String relatedPath) {
      myVariable = variable;
      myRelatedPath = relatedPath;
    }
  }
}
