#!python

# 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

from cylc.option_parsers import CylcOptionParser as COP
from cylc.network.client import SuiteRuntimeClient
from cylc.task_id import TaskID
from cylc.terminal import cli_function


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

    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, (suite, *task_args) = parser.parse_args()

    pclient = SuiteRuntimeClient(
        suite, options.owner, options.host, options.port,
        options.comms_timeout)
    json_filter = []

    if not task_args:
        # Print suite info.
        suite_info = pclient('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_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_task_requisites',
            {'task_globs': 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__":
    main()
