#!/usr/bin/env python

import csv
import re
import argparse
import os
import subprocess
import logging
import sys
import getpass
import platform
#import toml
from argparse import RawTextHelpFormatter
from pcgr import pcgr_vars, utils
from pcgr.arg_checker import get_docker_image_version
from pcgr.utils import check_subprocess, getlogger, error_message, warn_message

GE_panels = {
      0: "CPSR exploratory cancer predisposition panel (n = 433, Genomics England PanelApp / TCGA Germline Study / Cancer Gene Census / Other)",
      1: "Adult solid tumours cancer susceptibility (Genomics England PanelApp)",
      2: "Adult solid tumours for rare disease (Genomics England PanelApp)",
      3: "Bladder cancer pertinent cancer susceptibility (Genomics England PanelApp)",
      4: "Brain cancer pertinent cancer susceptibility (Genomics England PanelApp)",
      5: "Breast cancer pertinent cancer susceptibility (Genomics England PanelApp)",
      6: "Childhood solid tumours cancer susceptibility (Genomics England PanelApp)",
      7: "Colorectal cancer pertinent cancer susceptibility (Genomics England PanelApp)",
      8: "Endometrial cancer pertinent cancer susceptibility (Genomics England PanelApp)",
      9: "Familial Tumours Syndromes of the central & peripheral Nervous system (Genomics England PanelApp)",
      10: "Familial breast cancer (Genomics England PanelApp)",
      11: "Familial melanoma (Genomics England PanelApp)",
      12: "Familial prostate cancer (Genomics England PanelApp)",
      13: "Familial rhabdomyosarcoma (Genomics England PanelApp)",
      14: "GI tract tumours (Genomics England PanelApp)",
      15: "Genodermatoses with malignancies (Genomics England PanelApp)",
      16: "Haematological malignancies cancer susceptibility (Genomics England PanelApp)",
      17: "Haematological malignancies for rare disease (Genomics England PanelApp)",
      18: "Head and neck cancer pertinent cancer susceptibility (Genomics England PanelApp)",
      19: "Inherited MMR deficiency (Lynch Syndrome) - Genomics England PanelApp",
      20: "Inherited non-medullary thyroid cancer (Genomics England PanelApp)",
      21: "Inherited ovarian cancer (without breast cancer) (Genomics England PanelApp)",
      22: "Inherited pancreatic cancer (Genomics England PanelApp)",
      23: "Inherited polyposis (Genomics England PanelApp)",
      24: "Inherited predisposition to acute myeloid leukaemia (AML) - Genomics England PanelApp",
      25: "Inherited predisposition to GIST (Genomics England PanelApp)",
      26: "Inherited renal cancer (Genomics England PanelApp)",
      27: "Inherited phaeochromocytoma and paraganglioma (Genomics England PanelApp)",
      28: "Melanoma pertinent cancer susceptibility (Genomics England PanelApp)",
      29: "Multiple endocrine tumours (Genomics England PanelApp)",
      30: "Multiple monogenic benign skin tumours (Genomics England PanelApp)",
      31: "Neuroendocrine cancer pertinent cancer susceptibility (Genomics England PanelApp)",
      32: "Neurofibromatosis Type 1 (Genomics England PanelApp)",
      33: "Ovarian cancer pertinent cancer susceptibility (Genomics England PanelApp)",
      34: "Parathyroid Cancer (Genomics England PanelApp)",
      35: "Prostate cancer pertinent cancer susceptibility (Genomics England PanelApp)",
      36: "Renal cancer pertinent cancer susceptibility (Genomics England PanelApp)",
      37: "Rhabdoid tumour predisposition (Genomics England PanelApp)",
      38: "Sarcoma cancer susceptibility (Genomics England PanelApp)",
      39: "Sarcoma susceptbility (Genomics England PanelApp)",
      40: "Thyroid cancer pertinent cancer susceptibility (Genomics England PanelApp)",
      41: "Tumour predisposition - childhood onset (Genomics England PanelApp)",
      42: "Upper gastrointestinal cancer pertinent cancer susceptibility (Genomics England PanelApp)"
}

panels = '\n'.join([f'{k} = {GE_panels[k]}' for k in GE_panels]) # for displaying in help

def get_args():

   program_description = "Cancer Predisposition Sequencing Reporter - report of " + \
      "clinically significant cancer-predisposing germline variants"
   program_options = " --input_vcf <INPUT_VCF> --pcgr_dir <PCGR_DIR> --output_dir <OUTPUT_DIR> --genome_assembly " + \
      " <GENOME_ASSEMBLY> --sample_id <SAMPLE_ID>"

   parser = argparse.ArgumentParser(description = program_description,
                                    formatter_class=RawTextHelpFormatter, usage="%(prog)s -h [options] " + str(program_options))
   parser._action_groups.pop()
   required = parser.add_argument_group('Required arguments')
   optional_panel = parser.add_argument_group("Panel options")
   optional_vep = parser.add_argument_group('VEP options')
   optional_vcfanno = parser.add_argument_group('vcfanno options')
   optional_other = parser.add_argument_group('Other options')

   optional_panel.add_argument('--panel_id',dest = "virtual_panel_id",type = str, default = "-1", help="Comma-separated string with identifier(s) of predefined virtual cancer predisposition gene panels,\n choose any combination of the following identifiers:\n" + str(panels))
   optional_panel.add_argument('--custom_list',dest = "custom_list",help="Provide custom list of genes from virtual panel 0 (single-column txt file with Ensembl gene identifiers),\n alternative to predefined panels provided with --panel_id)")
   optional_panel.add_argument('--custom_list_name',dest = "custom_list_name", default="Custom_Panel", help="Set name for custom made panel/list (single word - no whitespace), will be displayed in the report")
   optional_panel.add_argument('--diagnostic_grade_only', action="store_true",help="For panel_id's 1-42 (Genomics England PanelApp) - consider genes with a GREEN status only, default: %(default)s")


   optional_other.add_argument('--force_overwrite', action = "store_true", help='By default, the script will fail with an error if any output file already exists.\n You can force the overwrite of existing result files by using this flag, default: %(default)s')
   #optional_other.add_argument('--version', action='version', version='%(prog)s ' + str(CPSR_VERSION))
   optional_other.add_argument('--basic',action="store_true",help="Run functional variant annotation on VCF through VEP/vcfanno, omit Tier assignment/report generation (STEP 4), default: %(default)s")
   optional_other.add_argument('--no_vcf_validate', action = "store_true",help="Skip validation of input VCF with Ensembl's vcf-validator, default: %(default)s")
   optional_other.add_argument('--docker_uid', dest='docker_user_id', help='Docker user ID. Default is the host system user ID. If you are experiencing permission errors,\n try setting this up to root (`--docker_uid root`), default: %(default)s')
   optional_other.add_argument('--no_docker', action='store_true', dest='no_docker', default=False, help='Run the CPSR workflow in a non-Docker mode, default: %(default)s')
   optional_other.add_argument('--preserved_info_tags', dest ='preserved_info_tags', default='None', help='Comma-separated string of VCF INFO tags from query VCF that should be kept in CPSR output TSV')
   optional_other.add_argument('--report_theme',choices = ['default','cerulean','journal','flatly','readable','spacelab','united','cosmo','lumen','paper','sandstone','simplex','yeti'], default = 'default', help='Visual report theme (rmarkdown),  default: %(default)s' )
   optional_other.add_argument('--report_nonfloating_toc', action='store_true', help='Do not float the table of contents (TOC) in output HTML report, default: %(default)s')
   optional_other.add_argument('--report_table_display', choices = ['full','light'], default='light', help="Set the level of detail/comprehensiveness in interactive datables of HTML report, very comprehensive (option 'full') or slim/focused ('light'), default: %(default)s")
   optional_other.add_argument('--ignore_noncoding', action='store_true',dest='ignore_noncoding',default=False,help='Do not list non-coding variants in HTML report, default: %(default)s')
   optional_other.add_argument('--secondary_findings', action='store_true',dest='secondary_findings',default=False, help='Include variants found in ACMG-recommended list for secondary findings (v3.0), default: %(default)s')
   optional_other.add_argument('--gwas_findings', action='store_true',dest='gwas_findings',default=False, help='Report overlap with low to moderate cancer risk variants (tag SNPs) identified from genome-wide association studies, default: %(default)s')
   optional_other.add_argument('--gwas_p_value', type = float, default = 0.000005, dest = 'gwas_p_value',help='Required p-value for variants listed as hits from genome-wide association studies, default: %(default)s')
   optional_other.add_argument('--pop_gnomad',choices = ['afr','amr','eas','sas','asj','nfe','fin','global'], default='nfe', help='Population source in gnomAD used for variant frequency assessment (ACMG classification), default: %(default)s')
   optional_other.add_argument('--maf_upper_threshold', type = float, default = 0.9, dest = 'maf_upper_threshold',help='Upper MAF limit (gnomAD global population frequency) for variants to be included in the report, default: %(default)s')
   optional_other.add_argument('--classify_all', action='store_true',dest='classify_all',help='Provide CPSR variant classifications (TIER 1-5) also for variants with exising ClinVar classifications in output TSV, default: %(default)s')
   optional_other.add_argument('--clinvar_ignore_noncancer', action='store_true', help='Ignore (exclude from report) ClinVar-classified variants reported only for phenotypes/conditions NOT related to cancer, default: %(default)s')
   optional_other.add_argument('--debug',action='store_true',default=False, help='Print full docker commands to log, default: %(default)s')

   optional_vcfanno.add_argument('--vcfanno_n_proc', default = 4, type = int, help="Number of vcfanno processes (option '-p' in vcfanno), default: %(default)s")

   optional_vep.add_argument('--vep_n_forks', default = 4, type = int, help="Number of forks (option '--fork' in VEP), default: %(default)s")
   optional_vep.add_argument('--vep_buffer_size', default = 500, type = int, help="Variant buffer size (variants read into memory simultaneously, option '--buffer_size' in VEP) " + \
      "\n- set lower to reduce memory usage, default: %(default)s")
   #optional_vep.add_argument('--vep_regulatory', action='store_true', help = 'Enable Variant Effect Predictor (VEP) to look for overlap with regulatory regions (option --regulatory in VEP).')
   optional_vep.add_argument('--vep_gencode_all', action='store_true', help = "Consider all GENCODE transcripts with Variant Effect Predictor (VEP) (option '--gencode_basic' in VEP is used by default).")
   optional_vep.add_argument('--vep_pick_order', default = "canonical,appris,biotype,ccds,rank,tsl,length,mane", help="Comma-separated string " + \
      "of ordered transcript properties for primary variant pick\n ( option '--pick_order' in VEP), default: %(default)s")
   optional_vep.add_argument('--vep_no_intergenic', action = "store_true", help="Skip intergenic variants during processing (option '--no_intergenic' in VEP), default: %(default)s")

   required.add_argument('--input_vcf', help='VCF input file with germline query variants (SNVs/InDels).', required = True)
   required.add_argument('--pcgr_dir',help=f"Directory that contains the PCGR data bundle directory, e.g. ~/pcgr-{pcgr_vars.PCGR_VERSION}", required = True)
   required.add_argument('--output_dir',help='Output directory', required = True)
   required.add_argument('--genome_assembly',choices = ['grch37','grch38'], help='Genome assembly build: grch37 or grch38', required = True)
   required.add_argument('--sample_id',help="Sample identifier - prefix for output files", required = True)

   args = parser.parse_args()
   return vars(args)

def main():
    arg_dict = get_args()

    logger = getlogger('cpsr-validate-input-arguments')
    logger.info("STEP 0: Validate input data")

    # check parsed arguments
    check_args(arg_dict, logger)
    # check and get docker image version
    DOCKER_IMAGE_VERSION = get_docker_image_version(arg_dict, logger)
    ## Map local input directories and files to internal paths/volumes in container (Docker)
    host_directories = verify_input_files(arg_dict, logger)
    ## Run CPSR workflow
    run_cpsr(arg_dict, host_directories, DOCKER_IMAGE_VERSION)