pipeline {
    agent { label 'linux-slave' }
    options { timestamps() }

    stages {
        stage('Test') {
            steps {
                install()
                sh "npm run test"
                sh "npm run check"
            }
        }

        stage('Build') {
            steps {
                configure()
                buildProject()
                addReleaseChannels()
            }
        }

        stage('Deploy') {
            when { anyOf { branch 'develop' ; branch 'master' ; not { environment name: 'PROJECT', value: '' } } }
            steps {
                dir('./dist') {
                    withCredentials([string(credentialsId: "NPM_TOKEN_WRITE", variable: 'NPM_TOKEN')]) {
                        sh "echo //registry.npmjs.org/:_authToken=$NPM_TOKEN > $WORKSPACE/dist/.npmrc"
                    }
                    deployToS3()
                    deployToNPM()
                }
            }
        }
    }
}

def install() {
    withCredentials([string(credentialsId: "NPM_TOKEN_WRITE", variable: 'NPM_TOKEN')]) {
        if (isUnix()) {
            sh "echo //registry.npmjs.org/:_authToken=$NPM_TOKEN > $WORKSPACE/.npmrc"
        } else {
            bat "echo //registry.npmjs.org/:_authToken=$NPM_TOKEN > $WORKSPACE/.npmrc"
        }
    }

    if (isUnix()) {
        sh "npm install"
    } else {
        bat "npm install"
    }
}

def configure() {
    def manifest = readJSON file: './package.json'

    GIT_SHORT_SHA = GIT_COMMIT.substring(0, 7)
    PKG_VERSION = manifest.version
    METADATA = env.METADATA?.replaceAll(/[. \/#]/, '-')?.toLowerCase()
    TIMESTAMP = new Date().format("yyyyMMdd.HHmmss", TimeZone.getTimeZone('UTC'))

    if (METADATA) {
        BUILD_VERSION = "${PKG_VERSION}-custom.${TIMESTAMP}+${METADATA.replaceAll('-', '.')}"
        MANIFEST_NAME = "tags/${METADATA}.json"
        CHANNEL = null
    } else if (env.PROJECT) {
        BUILD_VERSION = "${PKG_VERSION}-custom.${TIMESTAMP}"
        MANIFEST_NAME = null
        CHANNEL = null
    } else if (env.BRANCH_NAME == 'master') {
        BUILD_VERSION = PKG_VERSION
        MANIFEST_NAME = 'app.json'
        CHANNEL = 'stable'
    } else {
        BUILD_VERSION = "${PKG_VERSION}-alpha.${env.BUILD_NUMBER}"
        MANIFEST_NAME = 'app.staging.json'
        CHANNEL = 'staging'
    }

    // Local directory paths
    DIR_LOCAL_RES = './res/'
    DIR_LOCAL_DIST = './dist/'
}

def buildProject() {
    sh "npm run clean"
    sh "VERSION=${BUILD_VERSION} npm run build"
    sh "echo ${GIT_SHORT_SHA} > ${DIR_LOCAL_DIST}SHA.txt"
}

def addReleaseChannels() {
    // Not Applicable
}

def deployToS3() {
    // Not Applicable
}

def deployToNPM() {
    if (env.ALLOW_NPM != 'false' && env.DEPLOY_CLIENT != 'No') {
        withCredentials([string(credentialsId: 'NPM_TOKEN_WRITE', variable: 'NPM_TOKEN')]) {
            sh "echo //registry.npmjs.org/:_authToken=$NPM_TOKEN > $WORKSPACE/.npmrc"
        }

        if (BUILD_VERSION == PKG_VERSION) {
            // Assume production release
            echo "publishing to npm, version: ${BUILD_VERSION}"
            sh "npm publish"
        } else if (!env.PROJECT) {
            // Assume staging release, and tag as 'alpha'
            echo "publishing pre-release version to npm: ${BUILD_VERSION}"
            sh "npm version --no-git-tag-version ${BUILD_VERSION}"
            sh "npm publish --tag alpha"
            sh "npm version --no-git-tag-version ${PKG_VERSION}"
        } else {
            // Tag as 'custom', to not interfere with alpha/latest tags
            echo "publishing pre-release version to npm: ${BUILD_VERSION}"
            sh "npm version --no-git-tag-version ${BUILD_VERSION}"
            sh "npm publish --tag custom"
            sh "npm version --no-git-tag-version ${PKG_VERSION}"
        }
    }
}
