import io.jenkins.blueocean.rest.impl.pipeline.PipelineNodeGraphVisitor
import io.jenkins.blueocean.rest.impl.pipeline.FlowNodeWrapper
import org.jenkinsci.plugins.workflow.flow.FlowExecution
import org.jenkinsci.plugins.workflow.graph.FlowNode
import org.jenkinsci.plugins.workflow.job.WorkflowRun


// // helper function to check whether a stage failed
// @NonCPS
// List getFailedStages(WorkflowRun run) {
//     List failedStages = []
//     FlowExecution exec = run.getExecution()
//     PipelineNodeGraphVisitor visitor = new PipelineNodeGraphVisitor(run)
//     def flowNodes = visitor.getPipelineNodes()
//
//     for (node in flowNodes) {
//         if (node.getType() != FlowNodeWrapper.NodeType.STAGE ) { continue; }
//         String nodeName = node.getDisplayName()
//         def nodeResult = node.getStatus().getResult()
//         def resultSuccess = io.jenkins.blueocean.rest.model.BlueRun$BlueRunResult.SUCCESS
//         if (nodeResult != resultSuccess) {
//             failedStages.add(nodeName)
//         }
//     }
//     return failedStages
// }


pipeline {
    agent any

    environment {
        PATH = "$WORKSPACE/miniconda/bin:$PATH"
        CORES = "28"
    }

    stages {
        stage('Setup Miniconda') {
            steps {
                sh '''#!/usr/bin/env bash
                printf "\ndownload miniconda\n"
                PY=$(grep conda-forge::python= requirements.yaml | tr -d -c 0-9)
                CO=$(grep conda-forge::conda= requirements.yaml | cut -d '=' -f2)
                URL=https://repo.anaconda.com/miniconda/Miniconda3-py${PY}_${CO}-1-Linux-x86_64.sh
                wget $URL -nv -O miniconda.sh

                printf "\ninstall miniconda\n"
                bash miniconda.sh -b -p $WORKSPACE/miniconda > /dev/null 2>&1

                printf "\nconfigure miniconda\n"
                conda config --set always_yes yes 
                conda config --set changeps1 false
                conda config --set channel_priority strict
                
                printf "\ninstall mamba\n"
                MA=$(cat requirements.yaml | grep mamba | cut -d '=' -f2)
                conda install -c conda-forge conda=$CO mamba=$MA

                printf "\ninstalling seq2science environment\n"
                mamba env create -f requirements.yaml

                printf "\ninstalling seq2science\n"
                source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                conda activate s2s
                pip install .

                # remove old cache files
                seq2science clean
                genomepy clean
                '''
            }
        }

        stage('Generate DAGs') {
            steps {
                parallel (
                    "1 Download & alignment" : {
                        sh '''#!/usr/bin/env bash
                        set -e
                        source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                        conda activate s2s

                        bash ./tests/dag_tests.sh alignment
                        '''
                    },
                    "2 ATAC-seq & ChIP-seq" : {
                        sh '''#!/usr/bin/env bash
                        set -e
                        source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                        conda activate s2s

                        bash ./tests/dag_tests.sh atac-seq
                        '''
                    },
                    "3 scATAC-seq" : {
                        sh '''#!/usr/bin/env bash
                        set -e
                        source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                        conda activate s2s

                        bash ./tests/dag_tests.sh scatac-seq
                        '''
                    },
                    "4 RNA-seq" : {
                        sh '''#!/usr/bin/env bash
                        set -e
                        source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                        conda activate s2s

                        bash ./tests/dag_tests.sh rna-seq
                        '''
                    },
                    "5 scRNA-seq" : {
                        sh '''#!/usr/bin/env bash
                        set -e
                        source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                        conda activate s2s

                        bash ./tests/dag_tests.sh scrna-seq
                        '''
                    },
                    "6 explain functionality" : {
                        sh '''#!/usr/bin/env bash
                        set -e
                        source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                        conda activate s2s

                        bash ./tests/dag_tests.sh explain
                        '''
                    },
                    "~ setup conda environments" : {
                        sh '''#!/usr/bin/env bash
                        set -e
                        source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                        conda activate s2s

                        bash ./tests/run_tests.sh prep_align
                        '''
                    }
                )
            }
        }


        stage('Download workflow') {
//             when {
//                 anyOf {
//                     // always fully build develop and master
//                     branch 'master'
//                     branch 'develop'
//
//                     // always run when jenkins, envs or configuration is changed
//                     changeset glob: 'Jenkins/*'
//                     changeset glob: 'envs/*'
//                     changeset 'rules/configuration.smk'
//
//                     // run when relevant rules are changed
//                     changeset glob: 'seq2science/workflows/download_fastq/*'
//                     changeset 'rules/get_fastq.smk'
//
//                     // run when last time you failed
//                     expression {
//                         return getFailedStages(Jenkins.instance.getItemByFullName("Snakemake-Workflows")\
//                         .getItem("$GIT_BRANCH")._getRuns().last()).contains("Test downloading")
//                     }
//                 }
//             }
            steps {
                sh '''#!/usr/bin/env bash
                set -e
                source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                conda activate s2s

                bash ./tests/run_tests.sh download
                '''
            }
        }


        stage('Alignment workflow') {
//             when {
//                 anyOf {
//                     // always fully build develop and master
//                     branch 'master'
//                     branch 'develop'
//
//                     // always run when jenkins, envs or configuration is changed
//                     changeset glob: 'Jenkins/*'
//                     changeset glob: 'envs/*'
//                     changeset 'rules/configuration.smk'
//
//                     // run when relevant rules are changed
//                     changeset glob: 'seq2science/workflows/alignment/*'
//                     changeset 'rules/alignment.smk'
//                     changeset 'rules/trimming.smk'
//                     changeset 'rules/qc.smk'
//
//                     // run when last time you failed
//                     expression {
//                         return getFailedStages(Jenkins.instance.getItemByFullName("Snakemake-Workflows")\
//                         .getItem("$GIT_BRANCH")._getRuns().last()).contains("Test alignment")
//                     }
//                 }
//             }
            steps {
                parallel (
                    "Bowtie2" : {
                        sh '''#!/usr/bin/env bash
                        set -e
                        source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                        conda activate s2s

                        bash ./tests/run_tests.sh bowtie2
                        '''
                    },
                    "BWA1" : {
                        sh '''#!/usr/bin/env bash
                        set -e
                        source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                        conda activate s2s

                        bash ./tests/run_tests.sh bwa-mem1
                        '''
                    },
                    "BWA2" : {
                        sh '''#!/usr/bin/env bash
                        set -e
                        source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                        conda activate s2s

                        bash ./tests/run_tests.sh bwa-mem2
                        '''
                    },
                    "HISAT2" : {
                        sh '''#!/usr/bin/env bash
                        set -e
                        source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                        conda activate s2s

                        bash ./tests/run_tests.sh hisat2
                        '''
                    },
                    "MINIMAP2" : {
                        sh '''#!/usr/bin/env bash
                        set -e
                        source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                        conda activate s2s

                        bash ./tests/run_tests.sh minimap2
                        '''
                    },
                    "STAR" : {
                        sh '''#!/usr/bin/env bash
                        set -e
                        source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                        conda activate s2s

                        bash ./tests/run_tests.sh star
                        '''
                    }
                )
            }
        }


        stage('ATAC-seq workflow') {
//             when {
//                 anyOf {
//                     // always fully build develop and master
//                     branch 'master'
//                     branch 'develop'
//
//                     // always run when jenkins, envs or configuration is changed
//                     changeset glob: 'Jenkins/*'
//                     changeset glob: 'envs/*'
//                     changeset 'rules/configuration.smk'
//
//                     // run when relevant rules are changed
//                     changeset glob: 'seq2science/workflows/atac_seq/*'
//                     changeset 'rules/alignment.smk'
//                     changeset 'rules/trimming.smk'
//                     changeset 'rules/qc.smk'
//                     changeset 'rules/merge_replicates.smk'
//                     changeset 'rules/trackhub.smk'
//                     changeset 'rules/call_peak.smk'
//                     changeset 'rules/get_genome.smk'
//
//                     // run when last time you failed
//                     expression {
//                         return getFailedStages(Jenkins.instance.getItemByFullName("Snakemake-Workflows")\
//                         .getItem("$GIT_BRANCH")._getRuns().last()).contains("Test atac-seq")
//                     }
//                 }
//             }
            steps {
                sh '''#!/usr/bin/env bash
                set -e
                source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                conda activate s2s

                bash ./tests/run_tests.sh atac-seq
                '''
            }
        }

        stage('scATAC-seq workflow') {
            steps {
                sh '''#!/usr/bin/env bash
                set -e
                source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                conda activate s2s

                bash ./tests/run_tests.sh scatac-seq
                '''
            }
        }


        stage('RNA-seq workflow') {
//             when {
//                 anyOf {
//                     // always fully build develop and master
//                     branch 'master'
//                     branch 'develop'
//
//                     // always run when jenkins, envs or configuration is changed
//                     changeset glob: 'Jenkins/*'
//                     changeset glob: 'envs/*'
//                     changeset 'rules/configuration.smk'
//
//                     // run when relevant rules are changed
//                     changeset glob: 'seq2science/workflows/rna_seq/*'
//                     changeset 'rules/get_genome.smk'
//                     changeset 'rules/trimming.smk'
//                     changeset 'rules/alignment.smk'
//                     changeset 'rules/quantification.smk'
//                     changeset 'rules/gene_counts.smk'
//                     changeset 'rules/DGE_analysis.smk'
//                     changeset 'rules/qc.smk'
//                     changeset 'rules/trackhub.smk'
//
//                     // run when last time you failed
//                     expression {
//                         return getFailedStages(Jenkins.instance.getItemByFullName("Snakemake-Workflows")\
//                         .getItem("$GIT_BRANCH")._getRuns().last()).contains("Test rna-seq")
//                     }
//                 }
//             }
            steps {
                sh '''#!/usr/bin/env bash
                set -e
                source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                conda activate s2s

                bash ./tests/run_tests.sh rna-seq
                '''
            }
        }

        stage('deseq2science') {
            steps {
                sh '''#!/usr/bin/env bash
                set -e
                source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                conda activate s2s

                bash ./tests/run_tests.sh deseq2science
                '''
            }
        }

        stage('Code Style') {
            steps {
                catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
                    sh '''#!/usr/bin/env bash
                    set -e
                    source $WORKSPACE/miniconda/etc/profile.d/conda.sh
                    conda activate s2s
                    mamba install -q --yes flake8

                    # flake8
                    printf "\nflake8\n\n"
                    # E225: snakemake notation
                    # E501: snakemake lines are really long
                    # E731: lambdas improve readability in snakemake params
                    # E999: snakemake rule statement
                    # F722: snakemake include statement
                    # F821: snakemake globals
                    # W291: s2s logo uses trailing whitespaces
                    flake8 --ignore=E225,E501,E731,E999,F722,F821,W291 seq2science/*

                    # linting
                    printf "\nlinting\n\n"
                    snakemake -s seq2science/workflows/atac_seq/Snakefile --directory seq2science/workflows/atac_seq --lint
                    snakemake -s seq2science/workflows/rna_seq/Snakefile  --directory seq2science/workflows/rna_seq --lint
                    '''
                }
            }
       }
    }


    post {
        always {
            dir("$WORKSPACE") {
                deleteDir()
            }
        }
    }
}
