//file:noinspection GrMethodMayBeStatic // Disable because it has false positives
//file:noinspection GroovyAssignabilityCheck // Disable because it has false positives

import static org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_1

plugins {
	id 'org.jetbrains.intellij.platform' version '2.5.0'
	id 'org.jetbrains.kotlin.jvm' version '2.1.20'
	id 'java'
	id 'groovy'
}

repositories {
	mavenCentral()
	intellijPlatform {
		defaultRepositories()
	}
}

// Should match Kotlin version bundled with IntelliJ (see https://plugins.jetbrains.com/docs/intellij/using-kotlin.html#bundled-stdlib-versions)
// If the version is older, it will still work in IJ but is likely to be incompatible with Kotlin plugin which is often one version ahead.
ext.kotlinVersion = "2.1.20"
// Must match Groovy version bundled with IntelliJ (see IJ/Contents/lib/groovy.jar/META-INF/org.codehaus.groovy.runtime.ExtensionModule)
ext.groovyVersion = "3.0.19"
// For available IDE versions see "com.jetbrains.intellij.idea" in
// https://www.jetbrains.com/intellij-repository/releases and https://www.jetbrains.com/intellij-repository/snapshots
// 👇2025.2 needs PluginClassLoader_Fork fix; has script highlighting that works (unlike 2025.1)
ext.ideVersion = "252-EAP-SNAPSHOT"
ext.ideSandbox = "build/idea-sandbox/IC-2025.2"


intellijPlatform {
	projectName = "LivePlugin"
	instrumentCode = false // Not needed for LivePlugin (true by default in gradle plugin which is a bad idea)
	buildSearchableOptions = false // Disable because it takes a long time and the plugin doesn't need it
	pluginConfiguration {
		ideaVersion {
			untilBuild = provider { null } // Disable patching plugin.xml because "until" version is too restrictive (it's better to keep it open-ended)
		}
	}
}
dependencies {
	intellijPlatform {
		intellijIdeaCommunity(ideVersion, false)
		bundledPlugin "com.intellij.java"
		bundledPlugin "org.intellij.groovy"
		bundledPlugin "org.jetbrains.kotlin"
		bundledPlugin "Git4Idea"
		bundledPlugin "org.jetbrains.plugins.github"
		bundledPlugin "JUnit"
	}

	implementation project(":kotlin-compiler-wrapper")

	// Bundle Kotlin compiler and stdlib with LivePlugin because they are not always included into IDEs
	// and because Kotlin jars in IDE are likely to be updated, potentially breaking liveplugins,
	// so it should be more reliable to have a particular version of Kotlin jars inside LivePlugin.
	runtimeOnly "org.jetbrains.kotlin:kotlin-compiler-embeddable:$kotlinVersion"
	runtimeOnly "org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:$kotlinVersion"
	runtimeOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
	runtimeOnly "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"

	// Explicit Groovy dependency because even though Groovy is bundled with IJ,
	// it's not picked up by Groovy compiler in the latest versions.
	compileOnly "org.codehaus.groovy:groovy-all:$groovyVersion"
	testImplementation "org.codehaus.groovy:groovy-all:$groovyVersion"

	implementation "org.http4k:http4k-core:6.15.0.1"
	implementation "org.http4k:http4k-tools-traffic-capture:6.15.0.1"
	implementation("org.http4k:http4k-client-okhttp:6.15.0.1") {
		exclude group: "org.jetbrains.kotlin", module: "kotlin-stdlib-jdk8"
	}
	implementation "junit:junit:4.13.2"
	testImplementation "org.junit.jupiter:junit-jupiter-api:5.12.2"
	testImplementation "org.junit.platform:junit-platform-engine:1.12.2"
}
"Move kotlin compiler jars from plugin classpath into a separate folder so that there are no conflicts between kotlin and intellij classes"(ext.ideSandbox)
"Add source files to compiler output so that LivePlugin source code is available for navigation at runtime"()
'Copy GDSL file into standardDsls folder'(ext.ideSandbox)

sourceSets {
	main {
		// Keep Kotlin and Groovy API source code in separate folders for clarity.
		java { srcDir "src/main" }
		groovy { srcDir "src/plugin-api-groovy" }
		kotlin { srcDir "src/plugin-api-kotlin" }
		resources { srcDir "resources" }
		resources { srcDir "plugin-examples" }
	}
	test {
		groovy { srcDir "src/test" }
		kotlin { srcDir "src/test" }
	}
}
// Make Groovy compilation depend on Kotlin as described here
// https://docs.gradle.org/current/userguide/building_java_projects.html#sub:compile_deps_jvm_lang
tasks.named('compileGroovy') {
	classpath += files(sourceSets.main.kotlin.classesDirectory)
}

kotlin {
	jvmToolchain(17)
}
compileKotlin {
	compilerOptions {
		apiVersion.set(KOTLIN_2_1)
		languageVersion.set(KOTLIN_2_1)
		freeCompilerArgs = ["-Xskip-prerelease-check"]
	}
}

jar {
	duplicatesStrategy = DuplicatesStrategy.INCLUDE
}

tasks {
	publishPlugin {
		token.set(System.getenv("PUBLISH_TOKEN"))
		hidden.set(true)
	}
}

tasks.register('validateLivePluginZip') {
	doLast {
		def pluginZip = zipTree("build/distributions/LivePlugin.zip")
		def pluginZipFiles = pluginZip.files.collect { it.path.replaceFirst(".*[/\\\\]zip_.*?[/\\\\]", "").replace("\\", "/") }

		def kotlinCompilerAndItsTransitiveDependencies = [
			"LivePlugin/kotlin-compiler/annotations-13.0.jar",
			"LivePlugin/kotlin-compiler/kotlin-compiler-embeddable-2.1.20.jar",
			"LivePlugin/kotlin-compiler/kotlin-compiler-wrapper.jar",
			"LivePlugin/kotlin-compiler/kotlin-daemon-embeddable-2.1.20.jar",
			"LivePlugin/kotlin-compiler/kotlin-reflect-2.1.20.jar",
			"LivePlugin/kotlin-compiler/kotlin-script-runtime-2.1.20.jar",
			"LivePlugin/kotlin-compiler/kotlin-scripting-common-2.1.20.jar",
			"LivePlugin/kotlin-compiler/kotlin-scripting-compiler-embeddable-2.1.20.jar",
			"LivePlugin/kotlin-compiler/kotlin-scripting-compiler-impl-embeddable-2.1.20.jar",
			"LivePlugin/kotlin-compiler/kotlin-scripting-jvm-2.1.20.jar",
			"LivePlugin/kotlin-compiler/kotlin-stdlib-2.1.20.jar",
			"LivePlugin/kotlin-compiler/kotlinx-coroutines-core-jvm-1.8.0.jar",
			"LivePlugin/kotlin-compiler/trove4j-1.0.20200330.jar",
			"LivePlugin/lib/hamcrest-core-1.3.jar",
			"LivePlugin/lib/http4k-client-okhttp-6.15.0.1.jar",
			"LivePlugin/lib/http4k-core-6.15.0.1.jar",
			"LivePlugin/lib/http4k-tools-traffic-capture-6.15.0.1.jar",
			"LivePlugin/lib/http4k-realtime-core-6.15.0.1.jar",
			"LivePlugin/lib/junit-4.13.2.jar",
			"LivePlugin/lib/okhttp-4.12.0.jar",
			"LivePlugin/lib/okio-jvm-3.6.0.jar",
		]
		def expectedLivePluginJars = [
			"LivePlugin/lib/live-plugin.jar",
			"LivePlugin/lib/standardDsls/livePluginCompletions.gdsl",
		]
		expectToBeEqual(pluginZipFiles.toSorted(), (expectedLivePluginJars + kotlinCompilerAndItsTransitiveDependencies).toSorted())

		def livePluginJar = zipTree(pluginZip.files.find { it.name == "live-plugin.jar" })
		def livePluginJarFiles = livePluginJar.files.collect { it.path.replaceFirst(".*[/\\\\]zip_.*?[/\\\\]", "").replace("\\", "/") }.toSet()
		expectToContain(livePluginJarFiles, [
			"liveplugin/implementation/LivePlugin.class",
			"liveplugin/PluginUtil.class",
			"liveplugin/PluginUtil.groovy",
			"liveplugin/Plugin_utilKt.class",
			"liveplugin/plugin-util.kt",
			"groovy/default-plugin.groovy",
			"kotlin/default-plugin.kts",
			"META-INF/plugin.xml",
		].toSet())
	}
}
buildPlugin.finalizedBy(validateLivePluginZip)

static expectToContain(Set actual, Set expected) {
	if (!actual.containsAll(expected)) {
		throw new GradleException(
			"Didn't contain expected:\n" +
			(expected - actual).join("\n") + "\n"
		)
	}
}

static expectToBeEqual(Collection actual, Collection expected) {
	if (actual != expected) {
		throw new GradleException(
			"Expected:\n" +
			expected.join("\n") + "\n" +
			"but was:\n" +
			actual.join("\n")
		)
	}
}

def "Add source files to compiler output so that LivePlugin source code is available for navigation at runtime"() {
	compileKotlin.doLast {
		ant.copy(toDir: sourceSets.main.kotlin.classesDirectory.get(), overwrite: true) {
			ant.fileset(dir: "./src/plugin-api-groovy", includes: "**/*")
			ant.fileset(dir: "./src/plugin-api-kotlin", includes: "**/*")
			ant.fileset(dir: "./src/main", includes: "**/LivePluginScript.kt")
		}
	}
}

def "Move kotlin compiler jars from plugin classpath into a separate folder so that there are no conflicts between kotlin and intellij classes"(idePath) {
	prepareSandbox.doLast {
		new File("$idePath/plugins/LivePlugin/lib")
			.listFiles().toList()
			.findAll { it.name.endsWith(".jar") && it.name != "LivePlugin.jar" }
			.findAll {
				it.name.startsWith("kotlin-")
					|| it.name.startsWith("jna-")
					|| it.name.startsWith("annotations-")
					|| it.name.startsWith("trove4j-")
					|| it.name.startsWith("kotlinx-")
			}
			.each {
				ant.move(
					file: "$idePath/plugins/LivePlugin/lib/${it.name}",
					tofile: "$idePath/plugins/LivePlugin/kotlin-compiler/${it.name}"
				)
			}
	}
}

def 'Copy GDSL file into standardDsls folder'(idePath) {
	prepareSandbox.doLast {
		def resourcesFolder = project.tasks.named(JavaPlugin.PROCESS_RESOURCES_TASK_NAME).get().destinationDir
		ant.copy(
			file: resourcesFolder.absolutePath + "/liveplugin/livePluginCompletions.gdsl",
			tofile: "$idePath/plugins/LivePlugin/lib/standardDsls/livePluginCompletions.gdsl",
			quiet: true
		)
	}
}
