#!/usr/bin/env python3
"""ChaosBridge API discovery example. Python 3 standard library only.

Set CHAOSBRIDGE_TOKEN to the token created in the device management UI.
python3 chaosbridge_api_example.py --url https://YOUR_DEVICE
python3 chaosbridge_api_example.py --url https://YOUR_DEVICE --engine-id ENGINE_ID
This example only reads engine and virtual-link information.
"""

import argparse
import json
import os
import sys
from urllib.error import HTTPError, URLError
from urllib.parse import quote, urlsplit
from urllib.request import Request, urlopen


def get_json(base_url, path, token):
    request = Request(base_url + path, headers={
        "Authorization": "Bearer " + token,
        "Accept": "application/json",
    })
    try:
        with urlopen(request, timeout=15) as response:
            payload = json.load(response)
    except HTTPError as error:
        raise RuntimeError("HTTP %s: check the address, token and permissions" % error.code) from None
    except (URLError, TimeoutError):
        raise RuntimeError("Unable to connect to the device within 15 seconds") from None
    except (ValueError, UnicodeError):
        raise RuntimeError("The device did not return valid JSON") from None
    if isinstance(payload, dict) and payload.get("success") is False:
        raise RuntimeError("The device returned success=false; check API permissions and device status")
    return payload


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--url", required=True, help="Device origin, e.g. https://YOUR_DEVICE")
    parser.add_argument("--engine-id", help="An engine ID returned by /api/v1/engines")
    args = parser.parse_args()
    parsed = urlsplit(args.url)
    if parsed.scheme not in ("http", "https") or not parsed.hostname or parsed.username or parsed.password or parsed.query or parsed.fragment or parsed.path not in ("", "/"):
        parser.error("--url must be an HTTP(S) device origin without credentials, path or query")
    token = os.environ.get("CHAOSBRIDGE_TOKEN", "").strip()
    if not token:
        parser.error("Set the CHAOSBRIDGE_TOKEN environment variable")
    base = args.url.rstrip("/") + "/api/v1"
    try:
        results = {"engines": get_json(base, "/engines", token)}
        if args.engine_id:
            path = "/engines/" + quote(args.engine_id, safe="") + "/virtual-links"
            results["virtual_links"] = get_json(base, path, token)
        print(json.dumps(results, ensure_ascii=False, indent=2))
    except RuntimeError as error:
        print(str(error), file=sys.stderr)
        return 1
    return 0


if __name__ == "__main__":
    sys.exit(main())
