/*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Config file for defining DSL2 per module options and publishing paths
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Available keys to override module options:
        ext.args   = Additional arguments appended to command in module.
        ext.args2  = Second set of arguments appended to command in module (multi-tool modules).
        ext.args3  = Third set of arguments appended to command in module (multi-tool modules).
        ext.prefix = File name prefix for output files.
----------------------------------------------------------------------------------------
*/

process {

    publishDir = [
        path: { "${params.outdir}/${task.process.tokenize(':')[-1].tokenize('_')[0].toLowerCase()}" },
        mode: params.publish_dir_mode,
        saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
    ]

    withName: CUSTOM_DUMPSOFTWAREVERSIONS {
        publishDir = [
            path: { "${params.outdir}/pipeline_info" },
            mode: params.publish_dir_mode,
            pattern: '*_versions.yml'
        ]
    }

    // Validate input raw
    withName: SAMPLESHEET_CHECK {
        publishDir = [
            path: { "${params.outdir}/pipeline_info" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    // Validate input assembled
    withName: SAMPLESHEET_CHECK_ASSEMBLED {
        publishDir = [
            path: { "${params.outdir}/pipeline_info" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '--assembled'
    }

    withName: 'FASTP' {
            publishDir = [
                [
                    path: { "${params.outdir}/fastp/${meta.id}" },
                    mode: params.publish_dir_mode,
                    pattern: "*.{html,json,log}"
                ],
                [
                    enabled: params.save_trimmed,
                    path: { "${params.outdir}/fastp/${meta.id}/" },
                    mode: params.publish_dir_mode,
                    pattern: "*.fastp.fastq.gz"
                ]
            ]
            ext.args = [ "--disable_quality_filtering --disable_length_filtering",
                params.trim_fastq              ?: "--disable_adapter_trimming",
                params.clip_r1 > 0             ? "--trim_front1 ${params.clip_r1}"            : "", // Remove bp from the 5' end of read 1
                params.clip_r2   > 0           ? "--trim_front2 ${params.clip_r2}"            : "", // Remove bp from the 5' end of read 2
                params.three_prime_clip_r1 > 0 ? "--trim_tail1 ${params.three_prime_clip_r1}" : "", // Remove bp from the 3' end of read 1 AFTER adapter/quality trimming has been performed
                params.three_prime_clip_r2 > 0 ? "--trim_tail2 ${params.three_prime_clip_r2}" : "", // Remove bp from the 3' end of read 2 AFTER adapter/quality trimming has been performed
                params.trim_nextseq            ? "--trim_poly_g"                              : "", // Apply the --nextseq=X option, to trim based on quality after removing poly-G tails
            ].join(" ").trim()
    }

    withName: 'GUNZIP_*' {
        publishDir = [
            [
                enabled: false
            ]
        ]
    }

    // Validate input assembled
    withName: VALIDATE_INPUT {
        publishDir = [
            path: { "${params.outdir}/validated_input" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    withName: FASTQC {
        ext.args = '--quiet'
    }

    withName: FASTQC_POSTASSEMBLY {
        publishDir = [
            path: { "${params.outdir}/fastqc/postassembly" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '--quiet'
    }

    withName: RENAME_FASTQ {
        publishDir = [
            enabled: false
        ]
    }

    withName: 'RENAME_FILE_*' {
        publishDir = [
            enabled: false
        ]
    }

    withName: MERGE_UMI {
        publishDir = [
            [
                enabled: false
            ]
        ]
    }

    // -----------------
    // sequence assembly
    // -----------------
    withName: PRESTO_FILTERSEQ {
        publishDir = [
            path: { "${params.outdir}/presto/01-filterseq/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    withName: PRESTO_FILTERSEQ_POSTASSEMBLY_SANS_UMI {
        publishDir = [
            path: { "${params.outdir}/presto/02-filterseq/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    withName: PRESTO_MASKPRIMERS_UMI {
        publishDir = [
            path: { "${params.outdir}/presto/02-maskprimers/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    withName: PRESTO_MASKPRIMERS_ALIGN {
        publishDir = [
            path: { "${params.outdir}/presto/02-maskprimers/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '--skiprc --pf CREGION'
        ext.args2 = '-f ID CREGION ERROR'
    }

    withName: PRESTO_ALIGN_CREGION {
        publishDir = [
            path: { "${params.outdir}/presto/internal_cregion/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '--skiprc --revpr --pf CREGION'
        ext.args2 = '-f ID PRIMER ERROR --outname cregion_alignment'
    }

    withName: PRESTO_MASKPRIMERS_EXTRACT {
        publishDir = [
            path: { "${params.outdir}/presto/02-maskprimers/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '--barcode --bf BARCODE'
        ext.args2 = '-f ID PRIMER ERROR PRSTART'
    }

    withName: PRESTO_MASKPRIMERS_POSTASSEMBLY_SANS_UMI {
        publishDir = [
            path: { "${params.outdir}/presto/03-maskprimers/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    withName: PRESTO_PAIRSEQ {
        publishDir = [
            path: { "${params.outdir}/presto/03-pairseq/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = "--coord illumina"
    }

    withName: PRESTO_PAIRSEQ_ALIGN {
        publishDir = [
            path: { "${params.outdir}/presto/03-pairseq/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '--1f CREGION --coord illumina'
    }

    withName: PRESTO_CLUSTERSETS {
        publishDir = [
            path: { "${params.outdir}/presto/04-clustersets/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    withName: PRESTO_PARSE_CLUSTER {
        publishDir = [
            path: { "${params.outdir}/presto/05-parse-clusters/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    withName: PRESTO_BUILDCONSENSUS_UMI {
        publishDir = [
            path: { "${params.outdir}/presto/06-build-consensus/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '--pf PRIMER'
        ext.args2 = '--pf PRIMER'
        ext.args3 = '-f ID BARCODE SEQCOUNT PRIMER PRCOUNT PRCONS PRFREQ CONSCOUNT ERROR'
    }

    withName: PRESTO_BUILDCONSENSUS_ALIGN {
        publishDir = [
            path: { "${params.outdir}/presto/06-build-consensus/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '--pf CREGION'
        ext.args2 = '--pf CREGION'
        ext.args3 = '-f ID BARCODE SEQCOUNT PRIMER PRCOUNT PRCONS PRFREQ CONSCOUNT ERROR'
    }

    withName: PRESTO_POSTCONSENSUS_PAIRSEQ {
        publishDir = [
            path: { "${params.outdir}/presto/07-postconsensus-pairseq/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    withName: PRESTO_ASSEMBLEPAIRS_UMI {
        publishDir = [
            path: { "${params.outdir}/presto/08-assemble-pairs/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '--coord presto --rc tail --1f CONSCOUNT PRCONS --2f CONSCOUNT PRCONS'
        ext.args2 = '-f ID BARCODE SEQCOUNT PRIMER PRCOUNT PRCONS PRFREQ CONSCOUNT LENGTH OVERLAP ERROR PVALUE'
    }

    withName: PRESTO_ASSEMBLEPAIRS_SEQUENTIAL {
        publishDir = [
            path: { "${params.outdir}/presto/08-assemble-pairs/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '--coord presto --rc tail --1f CONSCOUNT --2f CONSCOUNT PRCONS --minlen 8 --maxerror 0.3 --alpha 1e-5 --scanrev --minident 0.5 --evalue 1e-5 --maxhits 100 --aligner blastn'
        ext.args2 = '-f ID REFID LENGTH OVERLAP GAP ERROR PVALUE EVALUE1 EVALUE2 IDENTITY FIELDS1 FIELDS2'
    }

    withName: PRESTO_ASSEMBLEPAIRS_SANS_UMI {
        publishDir = [
            path: { "${params.outdir}/presto/01-assemble-pairs/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '--rc tail'
        ext.args2 = '-f ID SEQCOUNT PRIMER PRCOUNT PRFREQ LENGTH OVERLAP ERROR PVALUE'
    }

    withName: PRESTO_PARSEHEADERS_COLLAPSE_UMI {
        publishDir = [
            enabled: false
        ]
        ext.subcommand = 'collapse'
        ext.args = '-f CONSCOUNT --act min'
    }

    withName: PRESTO_PARSEHEADERS_PRIMERS_UMI {
        publishDir = [
            enabled: false
        ]
        ext.args = 'PRCONS PRCONS'
    }

    withName: PRESTO_PARSEHEADERS_CREGION {
        publishDir = [
            enabled: false
        ]
        ext.subcommand = 'rename'
        ext.args = '-f PRCONS -k CREGION'
    }

    withName: PRESTO_PARSEHEADERS_PRIMERS_SANS_UMI {
        publishDir = [
            enabled: false
        ]
        ext.args = 'PRIMER PRIMER'
    }

    withName: PRESTO_PARSEHEADERS_METADATA {
        publishDir = [
            enabled: false
        ]
        ext.args = '-f sample_id subject_id species pcr_target_locus'
    }

    withName: PRESTO_COLLAPSESEQ_UMI {
        publishDir = [
            path: { "${params.outdir}/presto/09-collapseseq/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '-n 20 --inner --uf PRCONS --cf CONSCOUNT --act sum'
        ext.args2 = '-f HEADER DUPCOUNT CONSCOUNT'
    }

    withName: PRESTO_COLLAPSESEQ_ALIGN {
        publishDir = [
            path: { "${params.outdir}/presto/09-collapseseq/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '-n 0 --inner --uf CREGION --cf CONSCOUNT --act sum --keepmiss'
        ext.args2 = '-f HEADER DUPCOUNT CONSCOUNT'
    }

    withName: PRESTO_COLLAPSESEQ_CREGION {
        publishDir = [
            path: { "${params.outdir}/presto/09-collapseseq/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '-n 0 --inner --uf PRCONS CREGION --cf CONSCOUNT --act sum --keepmiss'
        ext.args2 = '-f HEADER DUPCOUNT CONSCOUNT'
    }

    withName: PRESTO_COLLAPSESEQ_SANS_UMI {
        publishDir = [
            path: { "${params.outdir}/presto/04-collapseseq/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '-n 20 --inner'
        ext.args2 = '-f HEADER DUPCOUNT'
    }

    withName: PRESTO_SPLITSEQ_UMI {
        publishDir = [
            path: { "${params.outdir}/presto/10-splitseq/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '-f CONSCOUNT --num 2'
    }

    withName: PRESTO_SPLITSEQ_SANS_UMI {
        publishDir = [
            path: { "${params.outdir}/presto/05-splitseq/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '-f DUPCOUNT --num 2'
    }

    // -----------------
    // V(D)J annotation
    // -----------------

    withName: FETCH_DATABASES {
        publishDir = [
            path: { "${params.outdir}/databases" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename },
            enabled: params.save_databases
        ]
    }

    withName: 'UNZIP_DB' {
        publishDir = [
            [
                enabled: false
            ]
        ]
    }

    withName: CHANGEO_CONVERTDB_FASTA_FROM_AIRR {
        publishDir = [
            path: { "${params.outdir}/vdj_annotation/convert-db/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '--if sequence_id --sf sequence --mf cell_id consensus_count duplicate_count'
    }


    withName: CHANGEO_ASSIGNGENES {
        publishDir = [
            path: { "${params.outdir}/vdj_annotation/01-assign-genes/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '--format blast'
    }

    withName: CHANGEO_MAKEDB {
        publishDir = [
            path: { "${params.outdir}/vdj_annotation/02-make-db/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = '--regions default --format airr --extended'
    }

    withName: FILTER_QUALITY {
        publishDir = [
            path: { "${params.outdir}/vdj_annotation/03-quality-filter/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    withName: CHANGEO_PARSEDB_SPLIT {
        publishDir = [
            path: { "${params.outdir}/vdj_annotation/04-select-productive/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    withName: FILTER_JUNCTION_MOD3 {
        publishDir = [
            path: { "${params.outdir}/vdj_annotation/05-select-junction-mod3/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    withName: ADD_META_TO_TAB {
        publishDir = [
            path: { "${params.outdir}/vdj_annotation/06-annotate-metadata/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    // -------------------------------
    // QC filtering
    // -------------------------------

    withName: CHANGEO_CREATEGERMLINES {
        publishDir = [
            path: { "${params.outdir}/qc-filtering/bulk-qc-filtering/01-create-germlines/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    withName: REMOVE_CHIMERIC {
        publishDir = [
            path: { "${params.outdir}/qc-filtering/bulk-qc-filtering/02-chimera-filter/${meta.id}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    withName: DETECT_CONTAMINATION {
        publishDir = [
            path: { "${params.outdir}/qc-filtering/bulk-qc-filtering/03-detect_contamination" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    withName: COLLAPSE_DUPLICATES {
        publishDir = [
            path: { "${params.outdir}/qc-filtering/bulk-qc-filtering/04-collapse-duplicates" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        errorStrategy = 'retry'
    }

    // ------------------------------
    // Single cell QC
    // ------------------------------
    withName: SINGLE_CELL_QC {
        publishDir = [
            path: { "${params.outdir}/qc-filtering/single-cell-qc" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = ['outname':'', 'outputby':'sample_id']
    }

    // -------------------------------
    // Clonal analysis
    // -------------------------------

    withName: FIND_CLONAL_THRESHOLD {
        publishDir = [
            path: { "${params.outdir}/clonal_analysis/find_threshold" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = ['findthreshold_method':'gmm',
            'findthreshold_model':'gamma-norm',
            'findthreshold_edge':0.9,
            'findthreshold_cutoff':'user',
            'findthreshold_spc':0.995]
    }

    withName: REPORT_THRESHOLD {
        publishDir = [
            path: { "${params.outdir}/clonal_analysis/report_threshold" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = ['findthreshold_method':'gmm',
            'findthreshold_model':'gamma-norm',
            'findthreshold_edge':0.9,
            'findthreshold_cutoff':'user',
            'findthreshold_spc':0.995,
            'subsample':10000]
    }

    withName: DEFINE_CLONES_COMPUTE {
        publishDir = [
            path: { "${params.outdir}/clonal_analysis/define_clones" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = ['outname':'', 'model':'hierarchical',
                    'method':'nt', 'linkage':'single',
                    'min_n':30]
    }

    withName: DEFINE_CLONES_REPORT {
        publishDir = [
            path: { "${params.outdir}/clonal_analysis/define_clones" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = ['outname':'', 'model':'hierarchical',
                    'method':'nt', 'linkage':'single',
                    'min_n':30]
    }

    withName: DOWSER_LINEAGES {
        publishDir = [
            path: { "${params.outdir}/clonal_analysis/dowser_lineages" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = ['minseq':5,
                    'traits':'isotype',
                    'tips':'isotype']
    }

    // -------------------------------
    // Reports
    // -------------------------------

    withName: AIRRFLOW_REPORT {
        publishDir = [
            path: { "${params.outdir}" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
        ext.args = 'none'
    }

    withName: PARSE_LOGS {
        publishDir = [
            path: { "${params.outdir}/parsed_logs" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    withName: REPORT_FILE_SIZE {
        publishDir = [
            path: { "${params.outdir}/report_file_size" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

    withName: 'MULTIQC' {
        ext.args   = { params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' }
        publishDir = [
            path: { "${params.outdir}/multiqc" },
            mode: params.publish_dir_mode,
            saveAs: { filename -> filename.equals('versions.yml') ? null : filename }
        ]
    }

}
