#!/usr/bin/env python

""" freshmaker-cli - Read-only client for Freshmaker REST API


Example usage:
    - List all the events handled by Freshmaker on redhat staging instance:
        ./freshmaker-cli --redhat --stage
    - List particular events based on the event id:
        ./freshmaker-cli --redhat --stage 1 2 3
    - Search for events matching particular event key:
        ./freshmaker-cli --redhat --stage --search-key 29110
    - Search for events which lead built particular NVR in Koji:
        ./freshmaker-cli --redhat --stage --rebuilt-nvr NVR
    - Search for events which upated particular NVR:
        ./freshmaker-cli --redhat --stage --original-nvr NVR
    - Search for events building particular artifact name
        ./freshmaker-cli --redhat --stage --name httpd24-docker
"""

from __future__ import print_function

import textwrap
import argparse
import sys
import requests
from tabulate import tabulate

# Disable InsecureRequestWarning
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)


EVENT_TYPES = [
    "Module build state changed",
    "Module git definition changed",
    "RPM git definition changed",
    "Internal Freshmaker event type",
    "Container image git definition changed",
    "Bodhi update added to stable",
    "Koji task state changed",
    "Koji RPM signed",
    "Errata advisory RPMS signed"
]


def get_api_url(deployment, env):
    API_URLS = {
        "redhat": {
            "prod": "https://freshmaker.host.prod.eng.bos.redhat.com",
            "stage": "https://freshmaker.host.stage.eng.bos.redhat.com",
            "qe": "https://freshmaker.host.qe.eng.pek2.redhat.com",
            "dev": "https://freshmaker.host.dev.eng.pek2.redhat.com",
        },
        "fedora": {}
    }

    if deployment not in API_URLS:
        return None

    envs = API_URLS[deployment]
    if env not in envs:
        return None

    return envs[env]


def get_events_from_builds(api_url, rebuilt_nvr=None, original_nvr=None,
                           name=None):
    page = 1
    ids = []
    while True:
        print("Getting messages from Freshmaker, page", page)
        url = '%s/api/1/builds?page=%d' % (api_url, page)
        if rebuilt_nvr:
            url += "&rebuilt_nvr=" + rebuilt_nvr
        if original_nvr:
            url += "&original_nvr=" + original_nvr
        if name:
            url += "&name=" + name

        r = requests.get(url, verify=False)
        page += 1
        ret = r.json()
        items = ret["items"]
        if not items:
            break
        for item in items:
            if item["event_id"] not in ids:
                ids.append(item["event_id"])

    return get_freshmaker_events_by_ids(api_url, ids)


def get_freshmaker_events(api_url, search_key=None, rebuilt_nvr=None,
                          original_nvr=None, name=None):
    if rebuilt_nvr or original_nvr or name:
        return get_events_from_builds(api_url, rebuilt_nvr, original_nvr,
                                      name)

    page = 1
    events = []
    while True:
        print("Getting messages from Freshmaker, page", page)
        url = '%s/api/1/events?page=%d' % (api_url, page)
        if search_key:
            url += "&search_key=" + search_key

        r = requests.get(url, verify=False)
        page += 1
        ret = r.json()
        items = ret["items"]
        if not items:
            break
        events += items

    events = sorted(events, key=lambda k: k['id'])
    return events


def get_freshmaker_events_by_ids(api_url, ids):
    events = []
    for i in ids:
        print("Getting Freshmaker event id", i)
        url = '%s/api/1/events/%s' % (api_url, str(i))

        r = requests.get(url, verify=False)
        ret = r.json()
        if not "error" in ret:
            events += [ret]
        else:
            print(ret["error"])

    events = sorted(events, key=lambda k: k['id'])
    return events


def print_events(events):
    table = [["ID", "Event type", "Event key", "Number of builds"]]
    for event in events:
        row = [event["id"], EVENT_TYPES[event["event_type_id"]],
               event["search_key"], len(event["builds"])]
        table.append(row)
    print(tabulate(table, headers="firstrow"))


def print_detailed_events(events):
    for event in events:
        print("Event id:", event["id"])

        table = [["Build ID", "Task ID", "State", "Original NVR", "Rebuilt NVR", "State Reason"]]
        for build in event["builds"]:
            row = [build["id"], build["build_id"], build["state_name"],
                build["original_nvr"], build["rebuilt_nvr"], build["state_reason"]]
            table.append(row)
        print(tabulate(table, headers="firstrow"))


parser = argparse.ArgumentParser(
    description=textwrap.dedent(__doc__),
    formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument(
    '--stage', default=False, action='store_true',
    help="Use the staging environment.")
parser.add_argument(
    '--qe', default=False, action='store_true',
    help="Use the qe environment.")
parser.add_argument(
    '--dev', default=False, action='store_true',
    help="Use the dev environment.")
parser.add_argument(
    '--redhat', default=False, action='store_true',
    help="Use the redhat instances.")
parser.add_argument(
    'events', metavar='event', nargs='*',
    help='Event ids to be queried')
parser.add_argument(
    '--search-key', default=None,
    help="Search for events matching the search_key")
parser.add_argument(
    '--rebuilt-nvr', default=None,
    help="NVR of rebuilt artifact to search for")
parser.add_argument(
    '--original-nvr', default=None,
    help="NVR of original artifact to search for")
parser.add_argument(
    '--name', default=None,
    help="Name of artifact to search for")
args = parser.parse_args()

if args.redhat:
    deployment = "redhat"
else:
    deployment = "fedora"

if args.stage:
    env = "stage"
elif args.qe:
    env = "qe"
elif args.dev:
    env = "dev"
else:
    env = "prod"

api_url = get_api_url(deployment, env)
if not api_url:
    print("There is no Freshmaker instance for deployment %s and env %s" %( deployment, env))
    sys.exit(1)

if not args.events:
    events = get_freshmaker_events(api_url, search_key=args.search_key,
                                   rebuilt_nvr=args.rebuilt_nvr,
                                   original_nvr=args.original_nvr,
                                   name=args.name)
    print_events(events)
else:
    events = get_freshmaker_events_by_ids(api_url, args.events)
    print_detailed_events(events)
