/*
 * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

package org.jetbrains.kotlin.gradle

import com.google.gson.Gson
import com.google.gson.JsonObject
import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.targets.js.dsl.Distribution.Companion.DIST
import org.jetbrains.kotlin.gradle.testbase.*
import org.junit.jupiter.api.DisplayName
import kotlin.io.path.reader
import kotlin.test.assertNotNull

abstract class KotlinJsIrLibraryGradlePluginITBase : KGPBaseTest() {

    override val defaultBuildOptions = super.defaultBuildOptions.copy(
        jsOptions = BuildOptions.JsOptions(),
        // KT-75899 Support Gradle Project Isolation in KGP JS & Wasm
        isolatedProjects = BuildOptions.IsolatedProjectsMode.DISABLED,
    )

    @DisplayName("simple binary library")
    @GradleTest
    fun testSimpleJsBinaryLibrary(gradleVersion: GradleVersion) {
        project("simple-js-library", gradleVersion) {
            build("build") {
                assertFileInProjectExists("build/$DIST/js/productionLibrary/js-library.js")
                assertFileInProjectExists("build/$DIST/js/productionLibrary/package.json")
                assertFileInProjectExists("build/$DIST/js/productionLibrary/main.js")
                projectPath.resolve("build/$DIST/js/productionLibrary/package.json").reader()
                    .use { Gson().fromJson(it, JsonObject::class.java) }
                    .getAsJsonObject("dependencies")
                    ?.entrySet()?.associate { (k, v) -> k to v.asString }
                    .let { dependencies ->
                        assertNotNull(dependencies?.get("decamelize")) { "Direct npm dependency missing in package.json" }
                        assertNotNull(dependencies?.get("@js-joda/core")) { "Transitive npm dependency missing in package.json" }
                    }
            }
        }
    }

    @DisplayName("binary library and executable")
    @GradleTest
    fun testJsBinaryLibraryAndExecutable(gradleVersion: GradleVersion) {
        project("js-library-with-executable", gradleVersion) {
            build("build") {
                assertFileInProjectExists("build/$DIST/js/productionLibrary/js-library.js")
                assertFileInProjectExists("build/$DIST/js/productionLibrary/package.json")
                assertFileInProjectExists("build/$DIST/js/productionLibrary/main.js")
            }
        }
    }

    @DisplayName("binary library and executable both for browser and nodejs")
    @GradleTest
    fun testJsBinaryLibraryAndExecutableForBrowserAndNodejs(gradleVersion: GradleVersion) {
        project("js-library-with-executable-browser-nodejs", gradleVersion) {
            build("build") {
                assertFileInProjectExists("build/$DIST/js/productionLibrary/js-library.js")
                assertFileInProjectExists("build/$DIST/js/productionLibrary/package.json")
                assertFileInProjectExists("build/$DIST/js/productionLibrary/main.js")

                assertFileInProjectExists("build/$DIST/js/productionExecutable/js-library.js")
            }
        }
    }
}

@DisplayName("Kotlin/JS K1 IR library")
@JsGradlePluginTests
class KotlinK1JsIrLibraryGradlePluginIT : KotlinJsIrLibraryGradlePluginITBase() {
    override val defaultBuildOptions = super.defaultBuildOptions.copyEnsuringK1()
}

@DisplayName("Kotlin/JS K2 IR library")
@JsGradlePluginTests
class KotlinK2JsIrLibraryGradlePluginIT : KotlinJsIrLibraryGradlePluginITBase() {
    override val defaultBuildOptions = super.defaultBuildOptions.copyEnsuringK2()
}
