#!/usr/bin/env python3
#
# Compare the clocks on two hoss
#

import datetime
import optparse
import pscheduler

pscheduler.set_graceful_exit()

#
# Gargle the arguments
#


class VerbatimParser(optparse.OptionParser):
    def format_epilog(self, formatter):
        return self.epilog

opt_parser = VerbatimParser(
    usage="Usage: %prog [ host [ host ] ]",
    epilog=
"""
Examples:

  clock
      Show the clock on the local host

  clock perfsonar6.example.org
      Compare the clock at perfsonar6.example.org the local host

  clock perfsonar6.example.org perfsonar7.example.org
      Compare the clocks at perfsonar6.example.org to perfsonar7.example.org
"""
    )
opt_parser.disable_interspersed_args()


opt_parser.add_option("--bind",
                      help="Make the request from the provided address",
                      default=None,
                      action="store", type="string",
                      dest="bind")
opt_parser.add_option("--timeout", "-W",
                      help="How long to wait for the server to respond, in seconds (default 15)",
                      default=15,
                      action="store", type="int",
                      dest="timeout")


(options, remaining_args) = opt_parser.parse_args()

if options.timeout <= 0:
    pscheduler.fail("Timeout must be >= 0")

if len(remaining_args) > 2:
    opt_parser.print_usage()
    pscheduler.fail()

num_args = len(remaining_args)

hosts = []

if num_args < 2:
    hosts.append("localhost")

hosts.extend(remaining_args)

results = []

for host in hosts:
    url = pscheduler.api_url(host, "clock")
    status, result = pscheduler.url_get(url, throw=False,
                                        bind=options.bind,
                                        timeout=options.timeout)

    if status == 400:
        pscheduler.fail("%s: %s" % (host, result))
    elif status in [ 202, 204, 205, 206, 207, 208, 226,
                     300, 301, 302, 303, 304, 205, 306, 307, 308 ] \
        or ( (status >= 400) and (status <=499) ):
        pscheduler.fail("%s is not running pScheduler" %  (host))
    elif status != 200:
        pscheduler.fail("%s returned status %d: %s" % (host, status, result))

    result["host"] = host

    results.append(result)


times = []

for result in results:
    try:
        times.append(pscheduler.iso8601_as_datetime(result["time"]))
        if "error" in result:
            sync_state = "error"
        else:
            sync_state = "synchronized  " if result["synchronized"] else "unsynchronized"
        print("%-10s %s %-14s %s" % (
            "clock",
            result["time"],
            sync_state,
            result["host"]
            ))

        if "error" in result:
            print("%-10s %s %s" % ("error", result["host"], result["error"]))

    except (KeyError, ValueError):
        pscheduler.fail("%s returned invalid data" % (host))

if len(results) < 2:
    pscheduler.succeed()

# Compare the two clocks

offset = max(times[0], times[1]) - min(times[0], times[1])
safe = offset < datetime.timedelta(seconds=1.0)
print("difference", pscheduler.timedelta_as_iso8601(offset), \
    "safe" if safe else "unsafe")

if not safe:
    pscheduler.fail()

pscheduler.succeed()
