#!/usr/bin/python3

# Copyright (c) 2007 - 2012 Canonical Ltd.
# Author: Martin Pitt <martin.pitt@ubuntu.com>
#
# 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 2 of the License, or (at your
# option) any later version.  See http://www.gnu.org/copyleft/gpl.html for
# the full text of the license.

"""CLI for maintaining the duplicate database"""

# pylint: disable=invalid-name
# pylint: enable=invalid-name

import argparse
import os.path
import sys

import apport.crashdb_impl.memory
import apport.logging


def command_dump(crashdb, _):
    """Print out all entries."""

    for sig, (crash_id, version, lastchange) in crashdb.duplicate_db_dump(True).items():
        sys.stdout.write(f"{crash_id:7d}: {sig} ")
        if version == "":
            sys.stdout.write("[fixed] ")
        elif version:
            sys.stdout.write(f"[fixed in: {version}] ")
        else:
            sys.stdout.write("[open] ")
        print(f"last change: {str(lastchange)}")


def command_changeid(crashdb, args):
    """Change the master ID of a crash."""
    crashdb.duplicate_db_change_master_id(args.old_id, args.new_id)


def command_removeid(crashdb, args):
    """Remove a crash."""
    crashdb.duplicate_db_remove(args.id)


def command_publish(crashdb, args):
    """Publish crash database to a directory."""
    crashdb.duplicate_db_publish(args.path)


def parse_args():
    """Parse command line options and return arguments."""
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-f",
        "--database-file",
        dest="db_file",
        metavar="PATH",
        default="apport_duplicates.db",
        help="Location of the database file (default: %(default)s)",
    )
    subparsers = parser.add_subparsers(metavar="command", required=True)

    parser_dump = subparsers.add_parser(
        "dump", help="Print a list of all database entries"
    )
    parser_dump.set_defaults(command=command_dump)

    parser_changeid = subparsers.add_parser(
        "changeid", help="Change the associated crash ID for a particular crash"
    )
    parser_changeid.set_defaults(command=command_changeid)
    parser_changeid.add_argument("old_id")
    parser_changeid.add_argument("new_id")

    parser_removeid = subparsers.add_parser(
        "removeid", help="Remove the associated crash ID for a particular crash"
    )
    parser_removeid.set_defaults(command=command_removeid)
    parser_removeid.add_argument("id")

    parser_publish = subparsers.add_parser(
        "publish",
        help="Export the duplicate database into a set of text files"
        " in the given directory which is suitable for WWW publishing",
    )
    parser_publish.set_defaults(command=command_publish)
    parser_publish.add_argument("path")

    return parser.parse_args()


# pylint: disable-next=missing-function-docstring
def main():
    args = parse_args()

    if not os.path.exists(args.db_file):
        apport.logging.fatal("file does not exist: %s", args.db_file)

    # pure DB operations don't need a real backend, and thus no crashdb.conf
    crashdb = apport.crashdb_impl.memory.CrashDatabase(None, {})
    crashdb.init_duplicate_db(args.db_file)
    args.command(crashdb, args)


if __name__ == "__main__":
    main()
