import subprocess
import os
import pandas as pd
import traceback
import argparse
from Alignment_Part import alignment


def runCmd(cmd):
    res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    sout, serr = res.communicate()
    return res.returncode, sout, serr
def dir_build(dir_path):
    cmd = f'mkdir -p {dir_path}'
    returncode, sout, serr = runCmd(cmd)
    print(cmd)
    if returncode == 0:
        final_result = "Build Dir."
    else:
        final_result = serr.decode("gbk")
    return returncode, final_result
def soft_build(input_file,dir_path):
    input_file = os.path.abspath(input_file)
    output_file = dir_path + os.path.basename(input_file)
    print(os.path.splitext(input_file)[-1])
    if os.path.splitext(input_file)[-1] != ".sorted":
        output_file = dir_path + os.path.basename(input_file) + ".sorted"
    cmd = f'ln -s {input_file} {output_file}'
    returncode, sout, serr = runCmd(cmd)
    print(cmd)
    if returncode == 0:
        final_result = "Soft Link Build."
    else:
        final_result = serr.decode("gbk")
    return returncode, final_result
def PHASMinerCLI(phasiRNA_len, dir_path, thread,sRNAminer):
    cmd = f'ls {dir_path}*.sorted | parallel -j {thread} "java -cp {sRNAminer} biocjava.sRNA.Miner.phasiRNA.PHASMinerCLI --inAln {{}} ' \
          f'--output {{}}.{phasiRNA_len}.PHAS.tab --phasLen {phasiRNA_len} --minUniqIdealLenCount 5 --normLibSize 20000000"'
    returncode, sout, serr = runCmd(cmd)
    if returncode == 0:
        final_result = "phasiRNAminer Step 1: Mining Lib [Finish]"
    else:
        final_result = serr.decode('gbk')
    return returncode, final_result


# def Merge_tab(input_file_list, phasiRNA_len,dir_path):
#     returncode = 0
#     return_str = ""
#     try:
#         output_file = open(dir_path + "all." + str(phasiRNA_len) + ".PHAS.list", "w+")
#         file_list = [os.path.basename(i) + "." + str(phasiRNA_len) +".PHAS.tab" for i in input_file_list]
#         for root, dirs, files in os.walk(dir_path):
#             for file in files:
#                 if file in file_list:
#                     output_file.write(root + file + "\n")
#         output_file.close()
#         return_str = "phasiRNAminer Step 2: Merging PHAS LIST [Finish]"
#     except Exception:
#         returncode += 1
#         return_str = traceback.format_exc()
#     return returncode,return_str

def PHASMerger(dir_path, phasiRNA_len, sRNAminer):
    input_file_1 = dir_path + "all." + str(phasiRNA_len) + ".PHAS.list"
    output_file = dir_path + "merged." + str(phasiRNA_len) + ".PHAS.list.xls"
    cmd = "java -cp " + sRNAminer + " biocjava.sRNA.Miner.phasiRNA.PHASMerger --inFileList " + input_file_1 + \
          " --outFile " + output_file
    returncode, sout, serr = runCmd(cmd)
    if returncode == 0:
        final_result = "phasiRNAminer Step 2: Merging PHAS file [Finish]"
    else:
        final_result = serr.decode('gbk')
    return returncode, final_result


def filter_phasiRNA_identification(dir_path, phasiRNA_len, lib_num, phas_score, pvalue):
    returncode = 0
    return_str = ""
    try:
        input_file_1 = dir_path + "merged." + str(phasiRNA_len) + ".PHAS.list.xls"
        output_file = dir_path + "merged." + str(phasiRNA_len) + ".PHAS.list.filter.xls"
        phasiRNA_filter = pd.read_table(input_file_1, encoding='utf-8')
        phasiRNA_filter = phasiRNA_filter[
            (phasiRNA_filter["Max_Region_Phase_Score"] >= int(phas_score)) & (phasiRNA_filter["Lib_Num"] >= int(lib_num)) & (phasiRNA_filter["Pvalue"] <= float(pvalue))& (phasiRNA_filter["Note"] != "Potential miRNA")]
        PHAS_name_list = []
        for i in range(1, len(phasiRNA_filter) + 1):
            PHAS_name_list.append("PHAS" + str(phasiRNA_len) + "-" + str(i))
        phasiRNA_filter["PHASID"] = PHAS_name_list
        phasiRNA_filter.to_csv(output_file, sep="\t", index=None)
        return_str = "phasiRNAminer Step 3: Filtering [Finish]"
        return returncode, return_str
    except Exception:
        returncode += 1
        return_str = traceback.format_exc()
        return returncode, return_str


def PHASMergedListToGFF(dir_path, genome_file, phasiRNA_len, sRNAminer):
    input_file_1 = dir_path + "merged." + str(phasiRNA_len) + ".PHAS.list.filter.xls"
    out_gff3_file = dir_path + "merged.PHAS" + str(phasiRNA_len) + ".gff3"
    cmd = "java -cp " + sRNAminer + " biocjava.sRNA.Miner.phasiRNA.PHASMergedListToGFF --inPhasList  " + input_file_1 + \
          " --outGff3 " + out_gff3_file + " --phasLen " + str(phasiRNA_len) + " --inGenome " + genome_file
    returncode, sout, serr = runCmd(cmd)
    if returncode == 0:
        final_result = "phasiRNAminer Step 4: Establishing GFF [Finish]"
    else:
        final_result = serr.decode('gbk')
    return returncode, final_result


def phas_identification_merger_pipeline(input_file_1, genome_file, phas_len, dir_path,
                                        lib_num, phas_score, pvalue,thread, Batch_mode, sRNAminer):
    print("Start...")
    final_result = ""
    returncode = 0
    n = 0

    if not dir_path.endswith("/") or dir_path.endswith("\\"):
        dir_path = dir_path + "/"
    final_dir_path = dir_path + "phasiRNA_identification/"
    while os.path.exists(final_dir_path):
        n += 1
        final_dir_path = dir_path + "phasiRNA_identification_" + str(n) + "/"
    dir_path = final_dir_path
    returncode, final_result = dir_build(dir_path)
    print(final_result)
    if returncode == 0:
        log_file = dir_path + "phasiRNA_identification.log"
        log_file_content = open(log_file, "w+")
        if Batch_mode:
            input_file_content = open(input_file_1, "r")
            file_list = [i.strip() for i in input_file_content.readlines()]
            new_file_list = []
            input_file_content.close()
            for input_file in file_list:
                returncode, final_result = soft_build(input_file,dir_path)
                if returncode == 0:
                    new_file_list.append(dir_path + os.path.basename(input_file) + "." + str(phas_len) + ".PHAS.tab")
            returncode, final_result = PHASMinerCLI(phas_len, dir_path,thread, sRNAminer)  # .tab
            print(final_result, file=log_file_content)

            if returncode == 0:
                print(final_result)
                check_num_PHAS_signal = 0
                all_phas_list_tmp = open(dir_path + "all." + str(phas_len) + ".PHAS.list", "w+")
                for i in new_file_list:
                    print(i, file=all_phas_list_tmp)
                    with open(i, "r") as f:
                        file_content = f.readlines()
                    if len(file_content) == 1:
                        check_num_PHAS_signal += 1
                all_phas_list_tmp.close()
                if check_num_PHAS_signal == len(new_file_list):
                    returncode += 1
                    final_result = "No PHAS locus is found in all Libs."
                    print(final_result, file=log_file_content)
                if returncode == 0:
                    returncode, final_result = PHASMerger(dir_path, phas_len, sRNAminer)
                    print(final_result, file=log_file_content)
                if returncode == 0:
                    print(final_result)
                    returncode, final_result = filter_phasiRNA_identification(dir_path, phas_len, lib_num, phas_score,
                                                                              pvalue)
                    print(final_result, file=log_file_content)
                    if returncode == 0:
                        print(final_result)
                        returncode, final_result = PHASMergedListToGFF(dir_path, genome_file, phas_len, sRNAminer)
                        print(final_result, file=log_file_content)

            print(final_result)



        else:
            file_list = str(input_file_1).split(",")
            new_file_list = []
            for input_file in file_list:
                returncode, final_result = soft_build(input_file, dir_path)
                if returncode == 0:
                    new_file_list.append(dir_path + os.path.basename(input_file) + "." + str(phas_len) + ".PHAS.tab")
            returncode, final_result = PHASMinerCLI(phas_len, dir_path, thread,sRNAminer)  # .tab
            print(final_result, file=log_file_content)

            if returncode == 0:
                print(final_result)
                check_num_PHAS_signal = 0
                all_phas_list_tmp = open(dir_path + "all." + str(phas_len) + ".PHAS.list", "w+")
                for i in new_file_list:
                    print(i, file=all_phas_list_tmp)
                    with open(i, "r") as f:
                        file_content = f.readlines()
                    if len(file_content) == 1:
                        check_num_PHAS_signal += 1
                all_phas_list_tmp.close()
                if check_num_PHAS_signal == len(new_file_list):
                    returncode += 1
                    final_result = "No PHAS locus is found in all Libs."
                    print(final_result, file=log_file_content)
                if returncode == 0:
                    returncode, final_result = PHASMerger(dir_path, phas_len, sRNAminer)
                    print(final_result, file=log_file_content)
                if returncode == 0:
                    print(final_result)
                    returncode, final_result = filter_phasiRNA_identification(dir_path, phas_len, lib_num, phas_score,
                                                                              pvalue)
                    print(final_result, file=log_file_content)
                    if returncode == 0:
                        print(final_result)
                        returncode, final_result = PHASMergedListToGFF(dir_path, genome_file, phas_len, sRNAminer)
                        print(final_result, file=log_file_content)

            print(final_result)

        log_file_content.close()
    if returncode == 0:
        print("Finish!")


if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument("--input_file", "-i", required=False, help="use_for_rfam")
    # parser.add_argument("--genome_file", "-g", required=False, help="use_for_rfam")
    args = parser.parse_args()
    input_file_arg = args.input_file
    print(input_file_arg)