#!/usr/bin/python3
import sys

import argparse
import yaml

import libnaklo3


def get_args():
    parser = argparse.ArgumentParser(
        description="tags files."
    )
    parser.add_argument(
        "-c", "--control-file", action="append",
        help="File of YAML-formatted control blocks",
    )
    parser.add_argument(
        "-p", "--preserve-existing", action="store_true",
        help="Preserve existing tags within input files",
    )

    group = parser.add_mutually_exclusive_group()
    group.add_argument(
        "-n", "--dry-run", action="store_true",
        help="Print what would be done, but don't do it",
    )
    group.add_argument(
        "-d", "--dot-dry-run", action="store_true",
        help="Visualize what would be done (in dot), but don't do it",
    )

    parser.add_argument(
        "songs", nargs=argparse.REMAINDER, metavar="<targets ...>"
    )

    args = parser.parse_args()

    if not args.songs:
        parser.error("No songs to tag.")
    return args


def get_tag_blocks(pathname):
    with open(pathname, "r") as tbfp:
        return yaml.safe_load(tbfp.read())


def add_control_files(controller, args):
    """Mutates a |controller| with tag blocks specified in |args|."""
    for pathname in args.control_file:
        tag_blocks = get_tag_blocks(pathname)
        controller.add_tag_blocks(tag_blocks)


def check_tag_propagation(tagged_songs):
    """Checks that any tag that ever appears, appears everywhere.

    This function assumes that any tag appearing at least once should
    appear on every song in `tagged_songs`. It prints a warning for each
    song missing any observed tag.
    """
    unique_tags = set()
    for song in tagged_songs:
        unique_tags.update(song.get_tag_keys())

    result = 0
    for song in tagged_songs:
        missing_tags = [tag for tag in unique_tags
                        if tag not in song.get_tag_keys()]
        missing_tags.sort()
        if missing_tags:
            result = 1
            print("WARNING: {} lacks {}".format(song.get_path(),
                                                ", ".join(missing_tags)))

    return result


def dry_run(tagged_songs):
    for song in tagged_songs:
        print(song)
    return check_tag_propagation(tagged_songs)


def main():
    args = get_args()

    songs = libnaklo3.songs_from(args.songs)
    controller = libnaklo3.NakloController(songs)

    add_control_files(controller, args)

    controller.apply_tags()
    if args.dry_run:
        return dry_run(songs)

    if not args.preserve_existing:
        controller.clear()
    controller.enact()
    return 0


if __name__ == "__main__":
    sys.exit(main())
