#
# The internetarchive module is a Python/CLI interface to Archive.org.
#
# Copyright (C) 2012-2021 Internet Archive
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""Retrieve information about your catalog tasks.

For more information on how to use this command, refer to the
Tasks API documentation::

    https://archive.org/services/docs/api/tasks.html

usage:
    ia tasks [--task=<task_id>...] [--get-task-log=<task_id>]
             [--parameter=<k:v>...] [--tab-output]
    ia tasks <identifier> [--parameter=<k:v>...] [--tab-output]
    ia tasks <identifier> --cmd=<command> [--comment=<comment>]
                          [--task-args=<k:v>...] [--data=<k:v>...]
                          [--tab-output] [--reduced-priority]
    ia tasks --get-rate-limit --cmd=<command>
    ia tasks --help

options:
    -h, --help
    -t, --task=<task_id>...       Return information about the given task.
    -G, --get-task-log=<task_id>  Return the given tasks task log.
    -p, --parameter=<k:v>...      URL parameters passed to catalog.php.
    -c, --cmd=<command>           The task to submit (e.g. make_dark.php).
    -C, --comment=<comment>       A reasonable explanation for why a
                                  task is being submitted.
    -T, --tab-output              Output task info in tab-delimited columns.
    -a, --task-args=<k:v>...      Args to submit to the Tasks API.
    -r, --reduced-priority        Submit task at a reduced priority.
                                  Note that it may take a very long time for
                                  your task to run after queued when this setting
                                  is used [default: False].
    -l, --get-rate-limit          Get rate limit info.
    -d, --data=<k:v>...           Additional data to send when submitting
                                  a task.

examples:
    ia tasks nasa
    ia tasks nasa -p cmd:derive.php  # only return derive.php tasks
    ia tasks -p 'args:*s3-put*'  # return all S3 tasks
    ia tasks -p 'submitter=jake@archive.org'  # return all tasks submitted by a user
    ia tasks --get-task-log 1178878475  # get a task log for a specific task

    ia tasks <id> --cmd make_undark.php --comment '<comment>'  # undark item
    ia tasks <id> --cmd make_dark.php --comment '<comment>'  # dark item
    ia tasks <id> --cmd fixer.php --task-args noop:1  # submit a noop fixer.php task
    ia tasks <id> --cmd fixer.php --task-args 'noop:1;asr:1'  # submit multiple fixer ops
    ia tasks --get-rate-limit --cmd derive.php  # Get rate-limit information for a specific command
"""
import sys
import warnings

from docopt import docopt

from internetarchive import ArchiveSession
from internetarchive.cli.argparser import get_args_dict
from internetarchive.utils import json


def main(argv, session: ArchiveSession) -> None:
    args = docopt(__doc__, argv=argv)

    # Tasks write API.
    if args['--cmd']:
        if args['--get-rate-limit']:
            r = session.get_tasks_api_rate_limit(args['--cmd'])
            print(json.dumps(r))
            sys.exit(0)
        data = get_args_dict(args['--data'], query_string=True)
        task_args = get_args_dict(args['--task-args'], query_string=True)
        data['args'] = task_args
        r = session.submit_task(args['<identifier>'],
                                args['--cmd'],
                                comment=args['--comment'],
                                priority=int(data.get('priority', 0)),
                                reduced_priority=args['--reduced-priority'],
                                data=data)
        j = r.json()
        if j.get('success'):
            task_log_url = j.get('value', {}).get('log')
            print(f'success: {task_log_url}', file=sys.stderr)
            sys.exit(0)
        elif 'already queued/running' in j.get('error', ''):
            print(f'success: {args["--cmd"]} task already queued/running', file=sys.stderr)
            sys.exit(0)
        else:
            print(f'error: {j.get("error")}', file=sys.stderr)
            sys.exit(1)

    # Tasks read API.
    params = get_args_dict(args['--parameter'], query_string=True)
    if args['<identifier>']:
        _params = {'identifier': args['<identifier>'], 'catalog': 1, 'history': 1}
        _params.update(params)
        params = _params
    elif args['--get-task-log']:
        log = session.get_task_log(args['--get-task-log'], params)
        print(log.encode('utf-8', errors='surrogateescape')
                 .decode('utf-8', errors='replace'))
        sys.exit(0)

    queryable_params = [
        'identifier',
        'task_id',
        'server',
        'cmd',
        'args',
        'submitter',
        'priority',
        'wait_admin',
        'submittime',
    ]

    if not (args['<identifier>']
            or params.get('task_id')):
        _params = {'catalog': 1, 'history': 0}
        _params.update(params)
        params = _params

    if not any(x in params for x in queryable_params):
        _params = {'submitter': session.user_email, 'catalog': 1, 'history': 0, 'summary': 0}
        _params.update(params)
        params = _params

    if args['--tab-output']:
        warn_msg = ('tab-delimited output will be removed in a future release. '
                    'Please switch to the default JSON output.')
        warnings.warn(warn_msg)
    for t in session.get_tasks(params=params):
        # Legacy support for tab-delimted output.
        # Mypy is confused by CatalogTask members being created from kwargs
        if args['--tab-output']:
            color = t.color if t.color else 'done'
            task_args = '\t'.join([f'{k}={v}' for k, v in t.args.items()])  # type: ignore
            output = '\t'.join([str(x) for x in [  # type: ignore
                t.identifier,  # type: ignore
                t.task_id,  # type: ignore
                t.server,  # type: ignore
                t.submittime,  # type: ignore
                t.cmd,  # type: ignore
                color,  # type: ignore
                t.submitter,  # type: ignore
                task_args,
            ] if x])
            print(output, flush=True)
        else:
            print(t.json(), flush=True)
