#!/usr/bin/env python
import sys
import httplib
import datetime
import time
import argparse
import urlparse

class TimedOut(Exception): pass

def dbg(msg):
    global _debug
    if _debug:
        return sys.stderr.write(msg)

def wait_until_code(code, netloc, path, name_of_service, timeout_secs, attempt_delay_secs=1):
    global _debug
    sys.stderr.write(u"Waiting for {0} to start...".format(name_of_service))
    start = datetime.datetime.now()
    timeout_delta = datetime.timedelta(seconds=timeout_secs)
    while True:
        try:
            conn = httplib.HTTPConnection(netloc, timeout=1)
            conn.request("HEAD", path)
            res = conn.getresponse()

            sys.stderr.write(u"Status: {0}".format(res.status))

            if res.status == code:
                now = datetime.datetime.now()
                delta = (now - start)
                waited = (delta.microseconds / 1e6) + (delta.seconds + delta.days * 24 * 3600)
                sys.stderr.write(u"\n{0} up in {1} seconds.".format(name_of_service, waited))
                break
            else:
                text_status = str(res.status)
                if len(text_status) > 0:
                    dbg(res.status)
                    sys.stderr.write(text_status[0])
                    sys.stderr.flush()
                else:
                    dbg(res.status)
                    sys.stderr.write("?")
                    sys.stderr.flush()
        except Exception, e:
            dbg(str(e))
            sys.stderr.write("X")
            sys.stderr.flush()

        now = datetime.datetime.now()
        if (start + timeout_delta) < now:
            delta = (now - start)
            waited = (delta.microseconds / 1e6) + (delta.seconds + delta.days * 24 * 3600)
            if _debug:
                sys.stderr.write('\n')
            sys.stderr.flush()
            raise TimedOut(
                u"Timed out waiting for {0} to start up, waited for {1} seconds.".format(
                    name_of_service, waited))

        time.sleep(attempt_delay_secs)


if __name__ == '__main__':
    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("-c", "--code", help="HTTP status code to wait for.", default=200, type=int)
    parser.add_argument("-u", "-url", "--url",
                        help="URL to wait for.",
                        default="http://localhost:34080/health", metavar="URL")
    parser.add_argument("-n", "--name", help="Name of service to wait for (for debugging purposes).",
                        default="application", metavar="NAME")
    parser.add_argument("-t", "--timeout",
                        help="Timeout for the health check.",
                        metavar="SECONDS", default=90, type=int)
    parser.add_argument("-d", "-x", "--debug", dest="debug", action="store_true",
                        help="Enable debug messages.")

    args = parser.parse_args()
    _debug = args.debug

    parsed = urlparse.urlparse(args.url)

    try:
        wait_until_code(args.code, parsed.netloc, parsed.path, args.name, args.timeout)
    except TimedOut, to:
        sys.stderr.write('\n')
        sys.stderr.flush()
        sys.exit(to)
