/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

import org.apache.tools.ant.filters.ReplaceTokens;
import org.gradle.plugins.ide.eclipse.model.SourceFolder
import org.gradle.plugins.ide.eclipse.model.ClasspathEntry

def resources = scriptResources(buildscript)

configure(rootProject) {
  apply plugin: "eclipse"

  def eclipseJavaVersion = propertyOrDefault("eclipse.javaVersion", rootProject.minJavaVersion)
  def relativize = { other -> rootProject.rootDir.relativePath(other).toString() }

  eclipse {
    project {
      name = "Apache Lucene ${version}"
    }

    classpath {
      defaultOutputDir = file('build/eclipse')

      file {
        beforeMerged { classpath -> classpath.entries.removeAll { it.kind == "src" } }

        whenMerged { classpath ->
          def projects = allprojects.findAll { prj ->
            return prj.plugins.hasPlugin(JavaPlugin)
          }
          
          Set<String> sourceSetNames = ['main', 'test', "main${eclipseJavaVersion}" as String, "test${eclipseJavaVersion}" as String, 'tools'] as Set
          Set<String> sources = []
          Set<File> jars = []
          projects.each { prj ->
            prj.sourceSets.each { sourceSet ->
              if (sourceSetNames.contains(sourceSet.name)) {
                sources += sourceSet.java.srcDirs.findAll { dir -> dir.exists() }.collect { dir -> relativize(dir) }
                sources += sourceSet.resources.srcDirs.findAll { dir -> dir.exists() }.collect { dir -> relativize(dir) }
              } 
            }

            // This is hacky - we take the resolved compile classpath and just
            // include JAR files from there. We should probably make it smarter
            // by looking at real dependencies. But then: this Eclipse configuration
            // doesn't really separate sources anyway so why bother.
            jars += prj.configurations.compileClasspath.resolve()
            jars += prj.configurations.testCompileClasspath.resolve()
          }

          classpath.entries += sources.sort().collect { name -> 
            def sourceFolder = new SourceFolder(name, "build/eclipse/" + name) 
            sourceFolder.setExcludes(["module-info.java"])
            return sourceFolder
          }
          classpath.entries += jars.unique().findAll { location -> location.isFile() && !(location.name ==~ /lucene-.*\.jar/) }.collect { location ->
            new LibEntry(location.toString())
          }
        }
      }
    }

    jdt {
      sourceCompatibility = eclipseJavaVersion
      targetCompatibility = eclipseJavaVersion
      javaRuntimeName = "JavaSE-$eclipseJavaVersion"
    }
  }

  task luceneEclipseJdt(type: Sync) {
    def errorMode = project.propertyOrDefault('eclipse.errors','warning');
    def ecjLintFile = rootProject.file('gradle/validation/ecj-lint/ecj.javadocs.prefs');
    
    description = 'Generates the Eclipse JDT settings file.'
    
    inputs.file(ecjLintFile)
    inputs.property('errorMode', errorMode)
    inputs.property('eclipseJavaVersion', eclipseJavaVersion as String)
  
    from rootProject.file("${resources}/dot.settings")
    into rootProject.file(".settings")
    filter(ReplaceTokens, tokens: [
      'ecj-lint-config': ecjLintFile.getText('UTF-8').replaceAll(/=error\b/, '=' + errorMode)
    ])
    filteringCharset = 'UTF-8'
    
    doLast {
      logger.lifecycle('Eclipse config for Java {} written with ECJ errors configured as {}. Change by passing -Peclipse.errors=ignore/warning/error.', eclipseJavaVersion, errorMode)
      logger.lifecycle('To edit classes of MR-JARs for a specific Java version, use e.g., -Peclipse.javaVersion=19')
    }
  }
  
  eclipseJdt {
    enabled = false    
    dependsOn 'luceneEclipseJdt'
  }
  
  eclipseClasspath {
    inputs.property('eclipseJavaVersion', eclipseJavaVersion as String)
  }
}

public class LibEntry implements ClasspathEntry {
  private String path;

  LibEntry(String path) {
    this.path = path;
  }

  @Override
  String getKind() {
    return "lib"
  }

  @Override
  void appendNode(Node node) {
    node.appendNode("classpathentry", Map.of(
        "kind", "lib",
        "path", path
    ));
  }
}