
import os
import math
import textwrap
import c4.utils
import subprocess

M_SQRT1_2 = 0.5**0.5

def find_path():
    if os.name == 'nt':
        default_path = "C:/WinCoot/runwincoot.bat"
        if os.path.exists(default_path):
            return default_path
        else:
            c4.utils.put_error("WinCoot not found.")
    else:
        return c4.utils.syspath("coot")

# returns tuple: coot path and version string
def find_path_and_version():
    coot_path = find_path()
    if not coot_path:
        return None, None
    # On Windows reading output from runwincoot.bat is not reliable,
    # and coot-real.exe --version works fine
    coot_for_ver = coot_path.replace('runwincoot.bat', 'bin/coot-real.exe')
    try:
        version_str = subprocess.check_output([coot_for_ver, "--version"])
    except subprocess.CalledProcessError:
        version_str = None
    return coot_path, version_str

def basic_script(pdb, mtz, center, toward):
    text = """\
        # coot script generated by dimple
        #set_nomenclature_errors_on_read("ignore")"""
    if pdb: text += """
        molecule = read_pdb('%s')""" % pdb
    if center: text += """
        set_rotation_centre(%g, %g, %g)
        set_zoom(30.)""" % center
    if toward: text += """
        set_view_quaternion(%g, %g, %g, %g)""" % view_as_quat(center, toward)
    if mtz: text += """
        mtz = '%s'
        map21 = make_and_draw_map(mtz, "2FOFCWT", "PH2FOFCWT", "", 0, 0)
        map11 = make_and_draw_map(mtz, "FOFCWT", "PHFOFCWT", "", 0, 1)""" % mtz
    return textwrap.dedent(text)


# view from p1 to p2, to be passed to set_view_quaternion()
def view_as_quat(p1, p2):
    if p1 is None or p2 is None:
        return (0., 0., 0., 1.)
    d = (p2[0]-p1[0], p2[1]-p1[1], p2[2]-p1[2])
    length = math.sqrt(d[0]*d[0] + d[1]*d[1] + d[2]*d[2])
    d = (d[0]/length, d[1]/length, d[2]/length)
    # ref vector: 0 0 -1 (?)
    # cross product (a2 b3 - a3 b2, ..., ...)
    prod = (d[1], -d[0], 0)
    quat = (prod[0], prod[1], prod[2], 1-d[2])
    qlen = math.sqrt(sum(a*a for a in quat))
    return (quat[0]/qlen, quat[1]/qlen, quat[2]/qlen, quat[3]/qlen)


def mult_quat(q1, q2):
    x, y, z, w = q1
    ax, ay, az, aw = q2
    return (w*ax + x*aw + y*az - z*ay,
            w*ay + y*aw + z*ax - x*az,
            w*az + z*aw + x*ay - y*ax,
            w*aw - x*ax - y*ay - z*az)


def r3d_script(center, toward, blobname):
    #quat0 = (0., 0., 0., 1.)
    quat0 = view_as_quat(center, toward)
    quaternions = [quat0, mult_quat(quat0, (0., M_SQRT1_2, 0., M_SQRT1_2)),
                          mult_quat(quat0, (M_SQRT1_2, 0., 0., M_SQRT1_2))]

    # Coot function raster3d() creates file.r3d, make_image_raster3d() also
    # calls render program and opens image (convenient for testing)
    basenames = []
    script = """
set_rotation_centre(%g, %g, %g)
set_zoom(30.)""" % center
    for n, quat in enumerate(quaternions):
        script += """
set_view_quaternion(%g, %g, %g, %g)""" % quat
        basename = "%sv%d" % (blobname, n+1)
        script += """
graphics_draw() # this is needed only for coot in --no-graphics mode
raster3d("%s.r3d")""" % basename
        basenames.append(basename)
    return script, basenames


