from django.http import HttpResponse
from django.shortcuts import render
from .forms import QueryForm

import os
import re
import logging
import pickle

# cmd = 'echo $LD_LIBRARY_PATH'
# r = os.popen(cmd).read()
# print('views.py library path=', r)
# import pandas as pd

log_level = 'DEBUG'
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
fn = os.path.join(BASE_DIR, 'all_protein_coding_gene_name.set.pkl')
hgnc_dict = pickle.load(open(fn, 'rb'))

fn = os.path.join(BASE_DIR, 'ddi_score_for_website.dict.pkl')
ddi = pickle.load(open(fn, 'rb'))
ddi_gn_set = set(ddi)

# print('\n'*4)
# print(f'using the ddi pdict using is {fn}')
# print(f'id for ddi dict = {id(ddi)}')

chrmap = {1: '1', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6', 7: '7', 8: '8', 9: '9', 10: '10', 11: '11', 12: '12',
          13: '13', 14: '14', 15: '15', 16: '16', 17: '17', 18: '18', 19: '19', 20: '20', 21: '21', 22: '22', 23: '23',
          24: '24', 25: '25', 26: '26', '1': '1', '2': '2', '3': '3', '4': '4', '5': '5', '6': '6', '7': '7', '8': '8',
          '9': '9', '10': '10', '11': '11', '12': '12', '13': '13', '14': '14', '15': '15', '16': '16', '17': '17',
          '18': '18', '19': '19', '20': '20', '21': '21', '22': '22', '23': '23', '24': '24', '25': '25', '26': '26',
          'chr1': '1', 'chr2': '2', 'chr3': '3', 'chr4': '4', 'chr5': '5', 'chr6': '6', 'chr7': '7', 'chr8': '8',
          'chr9': '9', 'chr10': '10', 'chr11': '11', 'chr12': '12', 'chr13': '13', 'chr14': '14', 'chr15': '15',
          'chr16': '16', 'chr17': '17', 'chr18': '18', 'chr19': '19', 'chr20': '20', 'chr21': '21', 'chr22': '22',
          'chr23': '23', 'chr24': '24', 'chr25': '25', 'chr26': '26', 'chr01': '1', 'chr02': '2', 'chr03': '3',
          'chr04': '4', 'chr05': '5', 'chr06': '6', 'chr07': '7', 'chr08': '8', 'chr09': '9', '01': '1', '02': '2',
          '03': '3', '04': '4', '05': '5', '06': '6', '07': '7', '08': '8', '09': '9', 'x': '23', 'y': '24', 'xy': '25',
          'mt': '26', '0x': '23', '0y': '24', 'X': '23', 'Y': '24', 'XY': '25', 'MT': '26', '0X': '23', '0Y': '24',
          'chrx': '23', 'chry': '24', 'chrxy': '25', 'chrmt': '26', 'chr0x': '23', 'chr0y': '24', 'chrX': '23',
          'chrY': '24', 'chrXY': '25', 'chrMT': '26', 'chr0X': '23', 'chr0Y': '24', 'chrM': '25', 'mito': '25', 'M':
          '25', 'm': '25', 'chrm': '25', 'Mito': '25'}


map_ddi = {'gn': 0,
    'dm': 1,
    'DDI': 2,
    'dmname': 3,
    'dmfull': 4,
    'DDI_rank': 5,
    'len_dm': 6,
    'len_cds': 7,
    'mis_cds': 8,
    'mis_dm': 9,
    'enrichment': 10,
    'path_count_dm': 11,
    'path_count_gene': 12,
    'or': 13,
    'chr': 14,
    'pos': 15,
    'strand': 16}

selected_fields_ddi_dict = ['DDI', 'DDI_rank', 'gn', 'dmname', 'dmfull', 'dm', 'chr', 'pos', 'strand', 'or']

map_zresult = {'gn': 0,
    'dm': 1,
    'DDI': 2,
    'dmname': 4,
    'dmfull': 5,
    'DDI_rank': 3,
    'or': 9,
    'chr': 6,
    'pos': 7,
    'strand': 8
    }



def home_view(request):
    igv_query = 'CACNA1A'
    input_error = ''
    input_error2 = ''
    valid = 1
    z_result = []
    z_result_sorted = []
    clinvar_gene = []

    table_header = ['DDI',
 'DDI rank',
 'Gene',
 'Domain Name',
 'Domain Full Name',
 'Pfam ID',
]

    if request.method == 'POST':
        form = QueryForm(request.POST)

        if form.is_valid():
            # get the value from the client-end input !
            normal = 1  # status , if some abormal occure, would not proceed the following steps
            query_item = form.cleaned_data['gene'].strip().upper()

            # the query is a range
            reg_range = re.compile(r'^(?:chr)?([\dxymt]+)[:\-]([\d ,]+)\-([\d ,]+)$')
            reg_range_single_positon = re.compile(r'^(?:chr)?([\dxymt]+)[:\-]([\d ,]+)\S*$')
            m_range1 = re.match(reg_range, query_item.lower())
            m_range2 = re.match(reg_range_single_positon, query_item.lower())
            if m_range1 or m_range2:
                # chrx:9991000-9992000
                try:
                    chr_, pos_s, pos_e = m_range1.groups()
                except:
                    chr_, pos_s = m_range2.groups()
                    pos_e = pos_s
                pos_s = re.sub("[, ]", '', pos_s)
                pos_e = re.sub("[, ]", '', pos_e)
                chr_ = chrmap[chr_]

                try:
                    pos_s = int(pos_s)+1
                    pos_e = int(pos_e)
                except:
                    normal = 0

                # the intersect
                if normal:
                    # print(f'chr_={chr_}, pos_s={pos_s}, pos_e={pos_e}')
                    igv_query = f'{chr_}:{pos_s}-{pos_e}'
                    cmd = f"""/var/www/html/miniconda/bin/bedtools intersect -a stdin -b {BASE_DIR}/static/files/range_dm.bed -wb <<<$'{chr_}\t{pos_s-1}\t{pos_e}'|cut -f 2,3,7,8 2>/dev/null"""
                    res = os.popen(cmd).read().strip().split('\n')
                    print('res=',res)
                    query_tmp = {}  # store the max and min value for the start and end

                    for ires in res:
                        try:
                            q_s, q_e, ign, idm_raw = ires.split('\t')
                            q_s = int(q_s)
                            q_e = int(q_e)
                        except:
                            print(f'error spliting  bedtools result {ires}')
                            normal = 0
                            continue

                        try:
                            if query_tmp[idm_raw][0] > q_s:
                                query_tmp[idm_raw][0] = q_s
                        except:
                            query_tmp[idm_raw] = [q_s, q_e, ign]

                        if query_tmp[idm_raw][1] < q_e:
                            query_tmp[idm_raw][1] = q_e

                    # get each domain
                # if normal:
                    check_dup = set()
                    for idm_raw, v in query_tmp.items():
                        idm, idm_sn = idm_raw.split('#')
                        q_s, q_e, ign = v
                        k = f'{ign}_{idm}'
                        if k not in check_dup:
                            check_dup.add(k)
                        else:
                            continue
                        try:
                            ddi_res = [ddi[ign][idm][map_ddi[_]] for _ in selected_fields_ddi_dict]
                        except:
                            print(f' this domain is not included in the DDI result : gn= {ign}, dm = {idm}')
                            continue

                        ddi_res.extend([q_s, q_e, chr_])
                        z_result.append(ddi_res)

                ##  sort the result, to enable the domains in the table are the same as the lollipop
                # must consider the strand issue
                # ['DDI', 'DDI_rank', 'gn', 'dmname', 'dmfull', 'dm', 'chr', 'pos', 'strand', 'or']
                if z_result:
                    reverse_tag = {'+': False, '-': True}[list(z_result)[0][-5]]  # strand = -5
                    z_result_sorted = sorted(z_result, key=lambda _: _[-6], reverse=reverse_tag)  # pos= -6
                    # -1 = domain sn
                    z_result_sorted = [[i[_] for _ in [0, 1, -1, -3, -2, 2, 3, 4, 5]] for i in z_result_sorted]
                    table_header.insert(2, 'Query_Match_End')
                    table_header.insert(2, 'Query_Match_Start')
                    table_header.insert(2, 'Chrom')

                    clinvar_gene.extend([_[2] for _ in z_result if _[-4] != 'NA'])  # or = -4
                else:
                    # check if this request is in other gene elements
                    cmd = f"""/var/www/html/miniconda/bin/bedtools intersect -a stdin -b {BASE_DIR}/static/files/range_cds_and_intron.bed -wb <<<$'{chr_}\t{pos_s-1}\t{pos_e}'|cut -f 2,3,5,6,7,8 2>/dev/null"""

                    res = os.popen(cmd).read().strip()
                    if not res:
                        input_error = '<div id="error"><span>The query range is outside of gene</span></div>'
                    else:
                        res = res.split('\n')
                        print(res)
                        tmp = res[0].split('\t')
                        ign = tmp[-2]
                        region = tmp[-1]
                        input_error2 = f'<div class="error"><span style="background: #ff8f6b;font-size:20px">The query range is the {region} region of gene {ign}, but outside of Pfam domain region</span></div>'

            # valid gene name
            elif query_item in hgnc_dict:
                igv_query = query_item
                table_header.insert(2, 'Chrom')
                if query_item not in ddi_gn_set:
                    # print('pos1')
                    valid = 0
                    input_error = '<div id="error"><span>Gene not found</span></div>'
                else:
                    #z_result = ddi.loc[ddi['gn'] == query_item].transpose().to_dict().values()
                    # print('pos1')
                    tmp = list(ddi[query_item].values())
                    # print(f'tmp={tmp}')
                    for dm_tmp in tmp:
                        chr_ = dm_tmp[map_ddi['chr']]
                        ddi_res = [dm_tmp[map_ddi[_]] for _ in selected_fields_ddi_dict]
                        ddi_res.append(chr_)
                        z_result.append(ddi_res)

                    # sort the result, to enable the domains in the table are the same as the lollipop
                    # must consider the strand issue
                    # ['DDI', 'DDI_rank', 'gn', 'dmname', 'dmfull', 'dm', 'chr', 'pos', 'strand', 'or']

                    reverse_tag = {'+': False, '-': True}[list(z_result)[0][-3]]  # strand = -2
                    z_result_sorted = sorted(z_result, key=lambda _: _[-3], reverse=reverse_tag)
                    z_result_sorted = [[i[_] for _ in [0, 1, -1, 2, 3, 4, 5]] for i in z_result_sorted]

                    # _[2] = ign
                    # _[-1] = odds ratio
                    clinvar_gene.extend([_[2] for _ in z_result if _[-1] != 'NA'])
            else:
                valid = 0
                input_error = '<div id="error"><span>not a protein coding gene or invalid input</span></div>'

                igv_query = query_item

        else:
            # print(f'is_bound {switch_toggle.is_bound}')
            valid = 0
            query_item = 'CACNA1A'
            igv_query = 'CACNA1A'
            input_error = '<div id="error"><span>Invalid Input</span></div>'

    # the unbounded request
    else:
        valid = 0
        query_item = 'CACNA1A'
        form = QueryForm()
#    print(f'error={input_error}, query_item={query_item}')
    return render(
        request, 't.html',
        {
            'form': form,
            'igv_query': igv_query,
            'query_item': query_item,
            'input_error': input_error,
            'input_error2': input_error2,
            'valid': valid,
            'z_result': z_result_sorted,
            'clinvar_gene': set(clinvar_gene),
            'table_header': table_header,
         })


def test_view(request, *args, **kwargs):
    for i in dir(request):
        res = eval(f'request.{i}')
        print(f'{i}  = {res}\n**************\n')
    return HttpResponse(f'<p> this is the test page <p>')
