#!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] documentation|browse [OPTIONS] ARGS

View documentation in the browser, as per Cylc global config.

% cylc doc [--local] [OPTIONS]
    Open the Cylc documentation.
% cylc doc [-t TASK] SUITE
    View suite or task documentation, if URLs are specified in the suite. This
    parses the suite definition to extract the requested URL."""

import sys

for arg in sys.argv[1:]:
    if arg.startswith('--host=') or arg.startswith('--user='):
        from cylc.remote import remrun
        if remrun(forward_x11=True):
            sys.exit(0)

import os
from subprocess import check_call, CalledProcessError

from cylc.cfgspec.glbl_cfg import glbl_cfg
from cylc.exceptions import UserInputError
from cylc.option_parsers import CylcOptionParser as COP
from cylc.run_get_stdout import run_get_stdout
from cylc.terminal import cli_function


@cli_function
def main():
    parser = COP(
        __doc__, argdoc=[('[TARGET]', 'File or suite name')])

    parser.add_option(
        "--local",
        help="Open the local documentation (if it has been built).",
        action="store_true", default=False, dest="local")

    parser.add_option(
        "-t", "--task", help="Browse task documentation URLs.",
        metavar="TASK_NAME", action="store", default=None, dest="task_name")

    parser.add_option(
        "-s", "--stdout", help="Just print the URL to stdout.",
        action="store_true", default=False, dest="stdout")

    parser.add_option(
        "--user",
        help="Other user account name. This results in "
             "command reinvocation on the remote account.",
        metavar="USER", action="store", dest="owner")

    parser.add_option(
        "--host",
        help="Other host name. This results in "
             "command reinvocation on the remote account.",
        metavar="HOST", action="store", dest="host")

    parser.add_option(
        "--debug",
        help="Print exception traceback on error.",
        action="store_true", default=False, dest="debug")

    options, args = parser.parse_args(remove_opts=['--host', '--user'])

    viewer = glbl_cfg().get(['document viewers', 'html'])
    if len(args) == 0:
        # Cylc documentation.
        if options.local:
            target = glbl_cfg().get(['documentation', 'local'])
        else:
            target = glbl_cfg().get(['documentation', 'online'])
        if target is None:
            raise UserInputError(
                "no url defined, see the [documentation][%s'] "
                "global configuration" % (
                    'local' if options.local else 'online'))

    elif len(args) == 1:
        # Suite or task documentation.
        suite = args[0]
        if options.task_name:
            # Task documentation.
            res, stdout = run_get_stdout(
                "cylc get-suite-config -i [runtime][%s][meta]URL %s" % (
                    options.task_name, suite))
        else:
            # Suite documentation.
            res, stdout = run_get_stdout(
                "cylc get-suite-config -i [meta]URL %s" % suite)
        if not res:
            # (Illegal config item)
            raise UserInputError(stdout)
        elif len(stdout) == 0:
            if options.task_name is not None:
                raise UserInputError("No URL defined for %s in %s." % (
                    options.task_name, suite))
            else:
                raise UserInputError("No URL defined for %s." % suite)
        target = stdout[0]
    else:
        parser.error("Too many arguments.")

    if options.stdout:
        print(target)
        sys.exit(0)

    # viewer may have spaces (e.g. 'firefox --no-remote'):
    command = ('%s %s' % (viewer, target)).split(' ')
    try:
        check_call(command, stdin=open(os.devnull))
    except CalledProcessError:
        print('failed to execute: %s' % command, file=sys.stderr)
        raise


if __name__ == "__main__":
    main()
