# L-6 MCS 507 Mon 1 Sep 2023 : call_mpsolve.py

"""
Python wrapper around unisolve program of MPSolve-2.2
or mpsolve of MPSolve-3.1.7.
"""

# PROGRAM='/Users/jan/Courses/MCS507/Fall13/Lec13/MPSolve-2.2/unisolve'
PROGRAM='/Users/jan/Courses/MCS507/Fall19/Lec06/MPSolve-3.1.7/src/mpsolve/mpsolve'

from sympy import var, Poly, degree

def mpsolve_integer_input(strpol):
    """
    Given in strpol is a string representing
    a polynomial in x with integer coefficients.
    On return is a string which can be
    written as an input file for unisolve.
    """
    x = var('x')
    pol = eval(strpol)
    # print('the expression p :', pol)
    qpol = Poly(pol)
    coeffs = qpol.all_coeffs()
    # print('the list of coefficients :', coeffs)
    coeffs.reverse()
    result = '! ' + strpol + '\n' + 'dri' + '\n'
    result = result + '0\n' + str(degree(qpol)) + '\n'
    for cff in coeffs:
        result = result + str(cff) + '\n'
    return result

def random_number(ndgts):
    """
    Returns a random number of ndgts digits long.
    """
    import random
    return random.randint(10**(ndgts-1), 10**ndgts)

def write_input_file(ipt):
    """
    Generates a random file name and writes the
    string ipt to file.
    Returns the name of the file.
    """
    name = 'in' + str(random_number(8))
    infile = open(name, 'w')
    infile.write(ipt)
    infile.close()
    return name

def get_unisolve_location():
    """
    Searches the command line for the location
    of the program, otherwise prompts the user.
    """
    import sys
    args = sys.argv
    if len(args) == 1:
        prog = input('give absolute path name for unisolve : ')
        if prog == "":
            print("Using", PROGRAM)
            prog = PROGRAM
    else:
        prog = args[1]
    return prog

def extract_roots(name):
    """
    Give the name of the output file,
    returns the roots in a list.
    """
    outfile = open(name,'r')
    lines = outfile.readlines()
    outfile.close()
    return [eval(e) for e in lines]

def mpsolve(pol, program=PROGRAM):
    """
    Given in the string pol a polynomial in x,
    returns a list of roots.
    """
    input_data = mpsolve_integer_input(pol)
    input_file = write_input_file(input_data)
    output_file = 'out' + str(random_number(8))
    cmd = program + ' ' + input_file + ' > ' + output_file
    import os
    os.system(cmd)
    roots = extract_roots(output_file)
    os.remove(input_file)
    os.remove(output_file)
    return roots

def main():
    """
    Prompts the user for a polynomial in x,
    and calls unisolve.
    """
    pol = input('give a polynomial in x : ')
    input_data = mpsolve_integer_input(pol)
    unisolve = get_unisolve_location()
    # print('writing', input_data)
    input_file = write_input_file(input_data)
    output_file = 'out' + str(random_number(8))
    cmd = unisolve + ' ' + input_file + ' > ' + output_file
    print('executing ' + cmd)
    import os
    os.system(cmd)
    print('the roots :', extract_roots(output_file))
    ans = input('remove input and output files ? (y/n) ')
    if ans == 'y':
        os.remove(input_file)
        os.remove(output_file)

if __name__ == '__main__':
    main()
