// Copyright 2016 The Bazel Authors. All rights reserved.
//
// 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.devtools.bazel.e4b.classpath;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.osgi.service.prefs.BackingStoreException;

import com.google.devtools.bazel.e4b.Activator;
import com.google.devtools.bazel.e4b.command.BazelCommand.BazelInstance;
import com.google.devtools.bazel.e4b.command.BazelNotFoundException;
import com.google.devtools.bazel.e4b.command.IdeBuildInfo;
import com.google.devtools.bazel.e4b.command.IdeBuildInfo.Jars;

public class BazelClasspathContainer implements IClasspathContainer {
  public static final String CONTAINER_NAME = "com.google.devtools.bazel.e4b.BAZEL_CONTAINER";

  private final IPath path;
  private final IJavaProject project;
  private final BazelInstance instance;

  public BazelClasspathContainer(IPath path, IJavaProject project)
      throws IOException, InterruptedException, BackingStoreException, JavaModelException,
      BazelNotFoundException {
    this.path = path;
    this.project = project;
    this.instance = Activator.getBazelCommandInstance(project.getProject());
  }

  private boolean isSourcePath(String path) throws JavaModelException, BackingStoreException {
    Path pp = new File(instance.getWorkspaceRoot().toString() + File.separator + path).toPath();
    IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
    for (IClasspathEntry entry : project.getRawClasspath()) {
      if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
        IResource res = root.findMember(entry.getPath());
        if (res != null) {
          String file = res.getLocation().toOSString();
          if (!file.isEmpty() && pp.startsWith(file)) {
            IPath[] inclusionPatterns = entry.getInclusionPatterns();
            if (!matchPatterns(pp, entry.getExclusionPatterns()) && (inclusionPatterns == null
                || inclusionPatterns.length == 0 || matchPatterns(pp, inclusionPatterns))) {
              return true;
            }
          }
        }
      }
    }
    return false;
  }

  private boolean matchPatterns(Path path, IPath[] patterns) {
    if (patterns != null) {
      for (IPath p : patterns) {
        PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + p.toOSString());
        if (matcher.matches(path)) {
          return true;
        }
      }
    }
    return false;
  }

  private boolean isSourceInPaths(List<String> sources)
      throws JavaModelException, BackingStoreException {
    for (String s : sources) {
      if (isSourcePath(s)) {
        return true;
      }
    }
    return false;
  }

  @Override
  public IClasspathEntry[] getClasspathEntries() {
    try {
      List<String> targets = Activator.getTargets(project.getProject());
      Map<String, IdeBuildInfo> infos = instance.getIdeInfo(targets);
      Set<Jars> jars = new HashSet<>();
      for (IdeBuildInfo s : infos.values()) {
        jars.addAll(s.getGeneratedJars());
        if (!isSourceInPaths(s.getSources())) {
          jars.addAll(s.getJars());
        }
      }
      return jarsToClasspathEntries(jars);
    } catch (JavaModelException | BackingStoreException | IOException | InterruptedException e) {
      Activator.error("Unable to compute classpath containers entries.", e);
      return new IClasspathEntry[] {};
    } catch (BazelNotFoundException e) {
      Activator.error("Bazel not found: " + e.getMessage());
      return new IClasspathEntry[] {};
    }
  }

  private IClasspathEntry[] jarsToClasspathEntries(Set<Jars> jars) {
    IClasspathEntry[] entries = new IClasspathEntry[jars.size()];
    int i = 0;
    File execRoot = instance.getExecRoot();
    for (Jars j : jars) {
      entries[i] = JavaCore.newLibraryEntry(getJarIPath(execRoot, j.getJar()),
          getJarIPath(execRoot, j.getSrcJar()), null);
      i++;
    }
    return entries;
  }

  private static IPath getJarIPath(File execRoot, String file) {
    if (file == null) {
      return null;
    }
    File path = new File(execRoot, file);
    return org.eclipse.core.runtime.Path.fromOSString(path.toString());
  }

  @Override
  public String getDescription() {
    return "Bazel Classpath Container";
  }

  @Override
  public int getKind() {
    return K_APPLICATION;
  }

  @Override
  public IPath getPath() {
    return path;
  }


  public boolean isValid() {
    return instance != null;
  }
}
