#!/usr/bin/env python
# encoding: utf-8
"""
Documentation for astrocalc can be found here: http://astrocalc.readthedocs.org

Usage:
    astrocalc [-c] coordflip <ra> <dec>
    astrocalc sep <ra1> <dec1> <ra2> <dec2>
    astrocalc timeflip <datetime>
    astrocalc trans <ra> <dec> <north> <east>
    astrocalc now mjd
    astrocalc dist (-z | -m) <distVal> [--hc=hVal --wm=OmegaMatter --wv=OmegaVacuum]

Commands:
    coordflip             flip coordinates between decimal degrees and sexegesimal and vice-versa
    sep                   calculate the separation between two locations in the sky.
    timeflip              flip time between UT and MJD.
    trans                 translate a location across the sky (north and east in arcsec)
    now                   report current time in various formats
    dist                  convert distance between mpc to z

Variables:
    ra, ra1, ra2          right-ascension in deciaml degrees or sexegesimal format
    dec, dec1, dec2       declination in deciaml degrees or sexegesimal format
    datetime              modified julian date (mjd) or universal time (UT). UT can be formated 20150415113334.343 or "20150415 11:33:34.343" (spaces require quotes)
    north, east           vector components in arcsec
    distVal               a distance value in Mpc (-mpc) or redshift (-z)
    hVal                  hubble constant value. Default=70 km/s/Mpc
    OmegaMatter           Omega Matter. Default=0.3
    OmegaVacuum           Omega Vacuum. Default=0.7

Options:
    init                                    setup the astrocalc settings file for the first time
    -v, --version                           show version
    -h, --help                              show this help message
    -m, --mpc                               distance in mpc
    -z, --redshift                          redshift distance
    -c, --cartesian                         convert to cartesian coordinates
    -s, --settings <pathToSettingsFile>     the settings file
"""
from __future__ import print_function
from builtins import str
import sys
import os
os.environ['TERM'] = 'vt100'
import readline
import glob
import pickle
from docopt import docopt
from fundamentals import tools, times
from astrocalc.coords import unit_conversion

def tab_complete(text, state):
    return (glob.glob(text + '*') + [None])[state]

def main(arguments=None):
    """
    *The main function used when `cl_utils.py` is run as a single script from the cl, or when installed as a cl command*
    """
    from astrocalc.coords import unit_conversion
    # setup the command-line util settings
    su = tools(
        arguments=arguments,
        docString=__doc__,
        logLevel="CRITICAL",
        options_first=True,
        projectName="astrocalc",
        defaultSettingsFile=True
    )
    arguments, settings, log, dbConn = su.setup()

    # tab completion for raw_input
    readline.set_completer_delims(' \t\n;')
    readline.parse_and_bind("tab: complete")
    readline.set_completer(tab_complete)

    # UNPACK REMAINING CL ARGUMENTS USING `EXEC` TO SETUP THE VARIABLE NAMES
    # AUTOMATICALLY
    a = {}
    for arg, val in list(arguments.items()):
        if arg[0] == "-":
            varname = arg.replace("-", "") + "Flag"
        else:
            varname = arg.replace("<", "").replace(">", "")
        a[varname] = val
        if arg == "--dbConn":
            dbConn = val
            a["dbConn"] = val
        log.debug('%s = %s' % (varname, val,))

    ## START LOGGING ##
    startTime = times.get_now_sql_datetime()
    log.info(
        '--- STARTING TO RUN THE cl_utils.py AT %s' %
        (startTime,))

    # set options interactively if user requests
    if "interactiveFlag" in a and a["interactiveFlag"]:

        # load previous settings
        moduleDirectory = os.path.dirname(__file__) + "/resources"
        pathToPickleFile = "%(moduleDirectory)s/previousSettings.p" % locals()
        try:
            with open(pathToPickleFile):
                pass
            previousSettingsExist = True
        except:
            previousSettingsExist = False
        previousSettings = {}
        if previousSettingsExist:
            previousSettings = pickle.load(open(pathToPickleFile, "rb"))

        # x-raw-input
        # x-boolean-raw-input
        # x-raw-input-with-default-value-from-previous-settings

        # save the most recently used requests
        pickleMeObjects = []
        pickleMe = {}
        theseLocals = locals()
        for k in pickleMeObjects:
            pickleMe[k] = theseLocals[k]
        pickle.dump(pickleMe, open(pathToPickleFile, "wb"))

    if a["init"]:
        from os.path import expanduser
        home = expanduser("~")
        filepath = home + "/.config/astrocalc/astrocalc.yaml"
        try:
            cmd = """open %(filepath)s""" % locals()
            p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)
        except:
            pass
        try:
            cmd = """start %(filepath)s""" % locals()
            p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)
        except:
            pass
        return

    coordflip = a["coordflip"]
    sep = a["sep"]
    timeflip = a["timeflip"]
    trans = a["trans"]
    now = a["now"]
    dist = a["dist"]
    ra = a["ra"]
    ra1 = a["ra1"]
    ra2 = a["ra2"]
    dec = a["dec"]
    dec1 = a["dec1"]
    dec2 = a["dec2"]
    datetime = a["datetime"]
    north = a["north"], east
    distVal = a["distVal"]
    hVal = a["hVal"]
    OmegaMatter = a["OmegaMatter"]
    OmegaVacuum = a["OmegaVacuum"]
    mpcFlag = a["mpcFlag"]
    redshiftFlag = a["redshiftFlag"]
    cartesianFlag = a["cartesianFlag"]

    # CALL FUNCTIONS/OBJECTS
    if coordflip:

        if cartesianFlag:
            converter = unit_conversion(
                log=log
            )
            x, y, z = converter.ra_dec_to_cartesian(
                ra="23 45 21.23232",
                dec="+01:58:5.45341"
            )
            print(x, y, z)
            return

        try:
            ra = float(ra)
            dec = float(dec)
            degree = True
        except Exception as e:
            degree = False

        if degree is True:
            converter = unit_conversion(
                log=log
            )
            try:
                ra = converter.ra_decimal_to_sexegesimal(
                    ra=ra,
                    delimiter=":"
                )
                dec = converter.dec_decimal_to_sexegesimal(
                    dec=dec,
                    delimiter=":"
                )
            except Exception as e:
                print(e)
                sys.exit(0)

            print(ra, dec)
        else:
            converter = unit_conversion(
                log=log
            )
            try:
                ra = converter.ra_sexegesimal_to_decimal(
                    ra=ra
                )
                dec = converter.dec_sexegesimal_to_decimal(
                    dec=dec
                )
            except Exception as e:
                print(e)
                sys.exit(0)
            print(ra, dec)

    if sep:
        from astrocalc.coords import separations
        calculator = separations(
            log=log,
            ra1=ra1,
            dec1=dec1,
            ra2=ra2,
            dec2=dec2,
        )
        angularSeparation, north, east = calculator.get()
        print("""%(angularSeparation)s arcsec (%(north)s N, %(east)s E)""" % locals())

    if timeflip:
        try:
            inputMjd = float(datetime)
            if datetime[0] not in ["0", "1", "2"]:
                inputMjd = True
            else:
                inputMjd = False
        except:
            inputMjd = False
        from astrocalc.times import conversions
        converter = conversions(
            log=log
        )

        if inputMjd == False:
            try:
                mjd = converter.ut_datetime_to_mjd(utDatetime=datetime)
                print(mjd)
            except Exception as e:
                print(e)
        else:
            try:
                utDate = converter.mjd_to_ut_datetime(mjd=datetime)
                print(utDate)
            except Exception as e:
                print(e)

    if trans:
        # TRANSLATE COORDINATES ACROSS SKY
        from astrocalc.coords import translate
        newRa, newDec = translate(
            log=log,
            ra=ra,
            dec=dec,
            northArcsec=float(north),
            eastArcsec=float(east)
        ).get()
        from astrocalc.coords import unit_conversion
        converter = unit_conversion(
            log=log
        )
        ra = converter.ra_decimal_to_sexegesimal(
            ra=newRa,
            delimiter=":"
        )
        dec = converter.dec_decimal_to_sexegesimal(
            dec=newDec,
            delimiter=":"
        )

        print("%(newRa)s, %(newDec)s (%(ra)s, %(dec)s)" % locals())

    if now:
        from astrocalc.times import now
        mjd = now(
            log=log
        ).get_mjd()
        print(mjd)

    if dist and redshiftFlag:
        from astrocalc.distances import converter
        c = converter(log=log)
        if not hcFlag:
            hcFlag = 70.
        if not wmFlag:
            wmFlag = 0.3
        if not wvFlag:
            wvFlag = 0.7
        dists = c.redshift_to_distance(
            z=float(distVal),
            WM=float(wmFlag),
            WV=float(wvFlag),
            H0=float(hcFlag)
        )
        print("Distance Modulus: " + str(dists["dmod"]) + " mag")
        print("Luminousity Distance: " + str(dists["dl_mpc"]) + " Mpc")
        print("Angular Size Scale: " + str(dists["da_scale"]) + " kpc/arcsec")
        print("Angular Size Distance: " + str(dists["da_mpc"]) + " Mpc")
        print("Comoving Radial Distance: " + str(dists["dcmr_mpc"]) + " Mpc")

    if dist and mpcFlag:
        from astrocalc.distances import converter
        c = converter(log=log)
        z = c.distance_to_redshift(
            mpc=float(distVal)
        )
        print("z = %(z)s" % locals())

    if "dbConn" in locals() and dbConn:
        dbConn.commit()
        dbConn.close()
    ## FINISH LOGGING ##
    endTime = times.get_now_sql_datetime()
    runningTime = times.calculate_time_difference(startTime, endTime)
    log.info('-- FINISHED ATTEMPT TO RUN THE cl_utils.py AT %s (RUNTIME: %s) --' %
             (endTime, runningTime, ))

    return

if __name__ == '__main__':
    main()
