plugins {
    id 'base'
    id 'com.github.node-gradle.node'
}

node {
    version = '22.19.0'
    download = true
}

def coreDir = layout.projectDirectory.dir( 'core' )

/* Clean */
clean {
    delete coreDir.dir( 'build' )
}

/* Test */
tasks.register( 'lint', NpmTask ) {
    dependsOn tasks.named( 'npmInstall' )
    description = 'Lint TS, JS, and JSON'
    args = ['run', 'lint']

    outputs.upToDateWhen { false }
}

check.dependsOn tasks.named( 'lint' )

/* Configure & Build */
tasks.register( 'typescript', NpmTask ) {
    dependsOn tasks.named( 'npmInstall' )
    dependsOn tasks.named( 'prepareToPublish' )
    description = 'Create JS and DTS files from TS'
    args = ['run', 'build']

    inputs.file "global.d.ts"
    inputs.files( fileTree( coreDir ) { include "**/*.ts" } )
    inputs.file "tsconfig.build.json"
    inputs.file "tsconfig.json"
    outputs.files( subprojects.collect {
        it.layout.buildDirectory.dir('typescript/lib/xp').map { d ->
            d.asFileTree.matching { include '**/*.js' }
        }
    } )
}

tasks.register( 'prepareToJsdoc', Copy ) {
    dependsOn tasks.named( 'typescript' )
    into layout.buildDirectory.dir( "js" )
    into( "" ) {
        from layout.projectDirectory
        include "lib-*/build/typescript/lib/xp/*.js"
        eachFile { fcd -> fcd.relativePath = new RelativePath( true, fcd.relativePath.segments.drop( 3 ) ) }
    }
    into( "examples" ) {
        from layout.projectDirectory
        include "lib-*/src/main/resources/lib/xp/examples/**/*.js"
        eachFile { fcd -> fcd.relativePath = new RelativePath( true, fcd.relativePath.segments.drop( 5 ) ) }
    }
    includeEmptyDirs = false
}

tasks.register( 'jsdoc', NpmTask ) {
    dependsOn tasks.named( 'prepareToJsdoc' )
    description = 'Build JSDoc for libraries.'
    args = ['run', 'jsdoc']
    doFirst {
        copy {
            from 'jsdoc/template/jsdoc-main.css'
            into layout.buildDirectory.dir( "resources/main/jsdoc/styles" )
        }
    }
}

/* Publish */
tasks.register( 'prepareGlobalToPublish', Copy ) {
    into layout.buildDirectory.dir( "npm" )
    from 'README.md'
    from 'global.d.ts'
    def dependencyLines = ['    "dependencies": {',
                           '        "@enonic-types/core": "' + version + '"',
                           '    }']
    from( 'package.template.json' ) {
        filter { line ->
            line
                .replaceAll( '%VERSION%', version )
                .replaceAll( '%FULL_NAME%|%FILE_NAME%', 'global' )
                .replaceAll( '%SHORT_NAME%', 'common' )
                .replaceAll( '%DESCRIPTION%', 'Global variables and functions type definition.' )
                .replaceAll( /    "dependencies": \{\}/, dependencyLines.join( '\n' ) )
        }
        rename '.+', 'package.json'
    }
}

tasks.register( 'prepareCoreToPublish', Copy ) {
    into "$coreDir/build/npm"
    from "$coreDir/README.md"
    from "$coreDir/index.d.ts"
    from( 'package.template.json' ) {
        filter { line ->
            line
                .replaceAll( '%VERSION%', version )
                .replaceAll( '%SHORT_NAME%', 'shared' )
                .replaceAll( '%FULL_NAME%', 'core' )
                .replaceAll( '%FILE_NAME%', 'index' )
                .replaceAll( '%DESCRIPTION%', 'Shared type definition for core libraries.' )
        }
        rename '.+', 'package.json'
    }
}

tasks.register( 'prepareToPublish' ) {
    dependsOn tasks.named( 'prepareGlobalToPublish' )
    dependsOn tasks.named( 'prepareCoreToPublish' )
}

tasks.register( 'publishGlobalToNpm', NpmTask ) {
    dependsOn tasks.named( 'prepareGlobalToPublish' )
    dependsOn tasks.named( 'npmInstall' )
    onlyIf { !version.endsWith( '-SNAPSHOT' ) }
    args = ['publish']
    workingDir = tasks.named( 'prepareGlobalToPublish' ).get().destinationDir
}

tasks.register( 'publishCoreToNpm', NpmTask ) {
    dependsOn tasks.named( 'prepareCoreToPublish' )
    dependsOn tasks.named( 'npmInstall' )
    onlyIf { !version.endsWith( '-SNAPSHOT' ) }
    args = ['publish']
    workingDir = tasks.named( 'prepareCoreToPublish' ).get().destinationDir
}

tasks.register( 'publish' ) {
    dependsOn tasks.named( 'publishGlobalToNpm' )
    dependsOn tasks.named( 'publishCoreToNpm' )
}

tasks.register( 'packageJsdoc', Jar ) {
    dependsOn tasks.named( 'jsdoc' )
    from layout.buildDirectory.dir( "resources/main/jsdoc" )
    archiveClassifier.set( 'jsdoc' )
}

assemble.dependsOn tasks.named( 'packageJsdoc' )

publishing {
    publications {
        mavenDocs( MavenPublication ) {
            artifact tasks.named( 'packageJsdoc' )
        }
    }
}

subprojects {p ->
    apply plugin: 'com.github.node-gradle.node'

    tasks.register( 'prepareToTypescript', Copy ) {
        from( "src/main/resources" ) {
            include '**/*.ts'
            includeEmptyDirs = false
        }
        into layout.buildDirectory.dir( "typescript" )
    }

    parent.tasks.named( 'typescript' ).configure {
        dependsOn tasks.named( 'prepareToTypescript' )
    }

    tasks.named( 'processResources' ) {
        from( layout.buildDirectory.dir( "typescript" ) ) {
            include '**/*.js'
        }
        dependsOn parent.tasks.named( 'typescript' )
    }

    tasks.register( 'prepareToPublish', Copy ) {
        dependsOn tasks.named( 'processResources' )

        def fullName = p.name
        def shortName = p.name.substring( 4 )
        def ts = p.file("src/main/resources/lib/xp/${shortName}.ts")
        def hasCore = ts.exists() && ts.getText('UTF-8').contains('@enonic-types/core')
        def dependencies = hasCore ? ['@enonic-types/core'] : []
        def depString = dependencies.collect { "        \"$it\": \"$p.version\"" }.join( ',\n' )
        into layout.buildDirectory.dir( "npm" )
        from( 'README.md' )
        from( layout.buildDirectory.dir( "typescript/lib/xp" ) ) {
            include '*.d.ts'
        }
        from( project(':lib').file('package.template.json') ) {
            filter { line ->
                def newLine = line
                    .replaceAll( '%VERSION%', p.version )
                    .replaceAll( '%FULL_NAME%', fullName )
                    .replaceAll( '%SHORT_NAME%|%FILE_NAME%', shortName )
                    .replaceAll( '%DESCRIPTION%', "Type definitions for ${fullName}." )
                if ( dependencies.size() > 0 )
                {
                    newLine = newLine.replaceAll( '"dependencies"\\: \\{\\}', "\"dependencies\": {\n$depString\n    }" )
                }
                return newLine
            }
            rename '.+', 'package.json'
        }
    }

    tasks.register( 'publishToNpm', NpmTask ) {
        dependsOn tasks.named( 'prepareToPublish' )
        onlyIf { !version.endsWith( '-SNAPSHOT' ) }
        args = ['publish']
        workingDir = tasks.named( 'prepareToPublish' ).get().destinationDir
    }

    publish.dependsOn tasks.named( 'publishToNpm' )

    check.dependsOn parent.tasks.named( 'lint' )

    jar {
        exclude '**/*.ts'
    }
}
