import subprocess
import numpy as np
import pandas as pd
import os, sys

# Set the value Display variable
os.environ.setdefault('DISPLAY', ':0.0')

# Simple function to perform bash operations 
def bash_command(cmd): 
    if os.name == 'nt':
        try:
            subprocess.run(['C:\\cygwin64\\bin\\bash.exe', '-l', cmd],  stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
        except:
            try:
                subprocess.run(['C:\\cygwin\\bin\\bash.exe', '-l', cmd],  stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
            except:
                sys.exit('Windows platforms need cygwin64/cygwin to run this subprocess')
        
    elif os.name == 'posix':    
        subprocess.run(['/bin/bash', '-c', cmd], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
    else:
        sys.exit('Could not verify OS')
    return 0

# ──────────────────────────────── RUNNING HASHRF RETURNING CLEANED OUTPUT ─────
#? From: "tqDist: a library for computing the quartet and triplet distances between binary or general trees" 
#? by A. Sand, C. N. S. Pedersen et al - 2014
#? https://www.birc.au.dk/~cstorm/software/tqdist/
# ──────────────────────────────────────────────────────────────────────────────

def quartet(file, n_trees, output_file):
    """compute quartet distances

    Args:
        file (str): name of input file with phylogenetic trees in newick format
        n_trees (int): number of trees in file
        output_file (str): name of output file that will contain the distance matrix

    Returns:
       distance_matrix (pandas.DataFrame): computed distance matrix
    """
    try: path = os.path.dirname(os.path.abspath(__file__))
    except: path = '.'
    cmd = '{path}/tqDist/bin/all_pairs_quartet_dist {file} {output} 1> /dev/null 2> ./tqdist_err.txt'.format(path = path,
        file= file, output= output_file, verbose = 1)
    
    # Runs command
    bash_command(cmd) 
    bash_command(f"tr -s \" \" < {output_file} | sed 's/\s/_/g' > ./tmp_file && cat ./tmp_file > {output_file} && rm ./tmp_file")

    # Reads output file and creates numpy array
    # which is used to create a pandas dataframe
    try:
        with open(output_file, 'r') as out:
            distance_matrix = np.zeros((n_trees, n_trees))
            for i,line in enumerate(out.readlines()):
                values = line.strip().split('_')[:-1]
                distance_matrix[i,:i+1] = values
            out.close()
        

        distance_matrix_upper = distance_matrix.transpose()
        distance_matrix = pd.DataFrame(distance_matrix + distance_matrix_upper)
        distance_matrix.to_csv(output_file)
        return distance_matrix
    except: print("quartet failed! check errors in hashrf_err.txt")
    

def triplet(file, n_trees, output_file):
    """compute triplet distances

    Args:
        file (str): name of input file with phylogenetic trees in newick format
        n_trees (int): number of trees in file
        output_file (str): name of output file that will contain the distance matrix

    Returns:
       distance_matrix (pandas.DataFrame): computed distance matrix
    """
    try: path = (os.path.dirname(__file__))
    except: path = '.'
    cmd = '{path}/tqDist/bin/all_pairs_quartet_dist {file} {output} 1> /dev/null 2> ./tqdist_err.txt'.format(path = path,
        file= file, output= output_file, verbose = 1)
    
    # Runs command
    bash_command(cmd) 
    bash_command(f"tr -s \" \" < {output_file} | sed 's/\s/_/g' > ./tmp_file && cat ./tmp_file > {output_file} && rm ./tmp_file")
    
    # Reads output file and creates numpy array
    # which is rused to create a pandas dataframe
    try:
        with open(output_file, 'r') as out:
            distance_matrix = np.zeros((n_trees, n_trees))
            for i,line in enumerate(out.readlines()):
                values = line.strip().split('_')[:-1]
                distance_matrix[i,:i+1] = values
            out.close()
        

        distance_matrix_upper = distance_matrix.transpose()
        distance_matrix = pd.DataFrame(distance_matrix + distance_matrix_upper)
        distance_matrix.to_csv(output_file)
        return distance_matrix
    except: print("triplet failed! check errors in hashrf_err.txt")



        
        
        
        
        
        
        
        
    
        










