#!/usr/bin/env python
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals

import os
import sys

import argcomplete

from tron.commands import cmd_utils
from tron.commands import display
from tron.commands.client import Client
from tron.commands.client import get_object_type_from_identifier
from tron.commands.client import RequestError
from tron.commands.client import TronObjectType
from tron.commands.cmd_utils import ExitCode
from tron.commands.cmd_utils import suggest_possibilities
from tron.commands.cmd_utils import tron_jobs_completer


def parse_cli():
    parser = cmd_utils.build_option_parser()
    parser.add_argument(
        "--numshown",
        "-n",
        type=int,
        dest="num_displays",
        help="Max number of jobs/job-runs shown",
        default=10,
    )
    parser.add_argument(
        "--color",
        "-c",
        action="store_true",
        dest="display_color",
        help="Display in color",
        default=None,
    )
    parser.add_argument(
        "--nocolor",
        action="store_false",
        dest="display_color",
        help="Display without color",
        default=None,
    )
    parser.add_argument(
        "--stdout",
        "-o",
        action="count",
        dest="stdout",
        help="Solely displays stdout",
        default=0,
    )
    parser.add_argument(
        "--stderr",
        "-e",
        action="count",
        dest="stderr",
        help="Solely displays stderr",
        default=0,
    )
    parser.add_argument(
        "--events",
        "-E",
        action="store_true",
        dest="events",
        help="Display stored events",
        default=0,
    )
    parser.add_argument(
        'name',
        nargs='?',
        help='job name | job run id | action id',
    ).completer = cmd_utils.tron_jobs_completer

    argcomplete.autocomplete(parser)
    args = parser.parse_args()
    return args


def console_height():
    if not sys.stdout.isatty():
        return 40
    return int(os.popen('stty size', 'r').read().split()[0])


def view_all(args, client):
    """Retrieve jobs and display them."""
    return display.DisplayJobs().format(
        client.jobs(
            include_job_runs=False,
            include_action_runs=False,
            include_action_graph=False,
            include_node_pool=False,
        )
    )


def view_job(args, job_id, client):
    """Retrieve details of the specified job and display"""
    job_content = client.job(job_id.url, count=args.num_displays)
    return display.format_job_details(job_content)


def view_job_run(args, job_run_id, client):
    actions = client.job_runs(job_run_id.url)
    display_action = display.DisplayActionRuns()
    return display_action.format(actions)


def view_action_run(args, act_run_id, client):
    content = client.action_runs(
        act_run_id.url,
        num_lines=args.num_displays,
    )
    return display.format_action_run_details(content)


obj_type_to_view_map = {
    TronObjectType.job: view_job,
    TronObjectType.job_run: view_job_run,
    TronObjectType.action_run: view_action_run,
}


def get_view_output(name, args, client):
    url_index = client.index()
    try:
        tron_id = get_object_type_from_identifier(url_index, name)
    except ValueError as e:
        possibilities = list(tron_jobs_completer(prefix='', client=client))
        suggestions = suggest_possibilities(
            word=name, possibilities=possibilities
        )
        raise SystemExit(f"Error: {e}{suggestions}")

    if tron_id.type not in obj_type_to_view_map:
        return

    try:
        return obj_type_to_view_map[tron_id.type](args, tron_id, client)
    except RequestError as e:
        raise SystemExit(f"Error: {e}")


def main():
    """run tronview"""
    args = parse_cli()
    cmd_utils.setup_logging(args)
    cmd_utils.load_config(args)

    display.Color.toggle(args.display_color)
    client = Client(args.server)

    try:
        if args.events:
            response = client.request("/api/events")
            error = response.get('error')
            if not error:
                for evt in response.get('response', ['* no recorded events *']):
                    print(evt)
                sys.exit(ExitCode.success)

        if not args.name:
            output = view_all(args, client)
        else:
            output = get_view_output(args.name, args, client)

        if not output:
            print("Unrecognized identifier: %s" % args.name, file=sys.stderr)
            sys.exit(ExitCode.fail)

        if sys.stdout.isatty() and len(output.split('\n')) > console_height():
            display.view_with_less(output, args.display_color)
        else:
            print(output)

    except RequestError as err:
        print(f"Error connecting to the tron server ({args.server}): {err}", file=sys.stderr)
        sys.exit(ExitCode.fail)


if __name__ == '__main__':
    main()
