#!/usr/bin/env python2

# THIS FILE IS PART OF THE CYLC SUITE ENGINE.
# Copyright (C) 2008-2019 NIWA & British Crown (Met Office) & Contributors.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""cylc [info] show [OPTIONS] ARGS

Interrogate a suite server program for the suite metadata; or for the metadata
of one of its tasks; or for the current state of the prerequisites, outputs,
and clock-triggering of a specific task instance."""

import sys
if '--use-ssh' in sys.argv[1:]:
    sys.argv.remove('--use-ssh')
    from cylc.remote import remrun
    if remrun():
        sys.exit(0)

import json

import cylc.flags
from cylc.option_parsers import CylcOptionParser as COP
from cylc.network.httpclient import SuiteRuntimeServiceClient
from cylc.task_id import TaskID


def main():
    """Implement "cylc show" CLI."""
    parser = COP(
        __doc__, comms=True, noforce=True, multitask=True,
        argdoc=[
            ('REG', 'Suite name'),
            ('[TASKID ...]', 'Task names or identifiers')])

    parser.add_option('--list-prereqs', action="store_true", default=False,
                      help="Print a task's pre-requisites as a list.")

    parser.add_option('--json', action="store_true", default=False,
                      help="Print output in JSON format.")

    options, args = parser.parse_args()
    suite = args[0]
    task_args = args[1:]
    pclient = SuiteRuntimeServiceClient(
        suite, options.owner, options.host, options.port,
        options.comms_timeout, my_uuid=options.set_uuid,
        print_uuid=options.print_uuid
    )
    json_filter = []

    if not task_args:
        # Print suite info.
        suite_info = pclient.get_info('get_suite_info')
        if options.json:
            json_filter.append(suite_info)
        else:
            for key, value in sorted(suite_info.items(), reverse=True):
                print '%s: %s' % (key, value or "(not given)")

    task_names = [arg for arg in task_args if TaskID.is_valid_name(arg)]
    task_ids = [arg for arg in task_args if TaskID.is_valid_id_2(arg)]

    if task_names:
        results = pclient.get_info('get_task_info', names=task_names)
        if options.json:
            json_filter.append(results)
        else:
            for task_name, result in sorted(results.items()):
                if len(results) > 1:
                    print "----\nTASK NAME: %s" % task_name
                for key, value in sorted(result.items(), reverse=True):
                    print "%s: %s" % (key, value or "(not given)")

    if task_ids:
        results, bad_items = pclient.get_info(
            'get_task_requisites', items=task_ids,
            list_prereqs=options.list_prereqs)
        if options.json:
            json_filter.append(results)
        else:
            for task_id, result in sorted(results.items()):
                if len(results) > 1:
                    print "----\nTASK ID: %s" % task_id
                if options.list_prereqs:
                    for prereq in result["prerequisites"]:
                        print prereq
                else:
                    for key, value in sorted(
                            result["meta"].items(), reverse=True):
                        print "%s: %s" % (key, value or "(not given)")

                    for name, done in [("prerequisites", "satisfied"),
                                       ("outputs", "completed")]:
                        print '\n%s (- => not %s):' % (name, done)
                        if not result[name]:
                            print '  (None)'
                        for msg, state in result[name]:
                            if state:
                                print '  + ' + msg
                            else:
                                print '  - ' + msg

                    if result["extras"]:
                        print '\nother:'
                        for key, value in result["extras"].items():
                            print '  o  %s ... %s' % (key, value)
            for bad_item in bad_items:
                sys.stderr.write("No matching tasks found: %s\n" % bad_item)
            if bad_items:
                sys.exit(1)

    if options.json:
        print json.dumps(json_filter, indent=4)


if __name__ == "__main__":
    try:
        main()
    except Exception as exc:
        if cylc.flags.debug:
            raise
        sys.exit(str(exc))
