#!/usr/bin/env python
"""License.sh

Usage:
  license-sh.py config
  license-sh.py [options]
  license-sh.py <path> [options]
  license-sh.py (-h | --help)
  license-sh.py --version

Options:
  -h --help                           Show this screen.
  -o <reporter> --output <reporter>   Output [default: console].
  -t --tree                           Show full dependency tree.
  -d --debug                          Debug mode
  --version                           Show version.
"""
from typing import List, Set, Tuple

from PyInquirer import prompt
from anytree import AnyNode

from license_sh.commands import config_cmd
from license_sh.config import whitelist_licenses, get_config
from license_sh.helpers import annotate_dep_tree, filter_dep_tree
from license_sh.reporters.ConsoleReporter import ConsoleReporter
from license_sh.reporters.JSONConsoleReporter import JSONConsoleReporter

from version import __version__

from docopt import docopt

from license_sh.project_identifier import get_project_types, ProjectType
from license_sh.runners.npm import NpmRunner
from license_sh.runners.yarn import YarnRunner
from license_sh.runners.python import PythonRunner
from license_sh.runners.maven import MavenRunner


def print_dependency_tree_with_licenses(
    dep_tree: AnyNode, whitelist: List[str]
) -> Tuple[AnyNode, Set[str]]:
    annotated_dep_tree, unknown_licenses = annotate_dep_tree(
        dep_tree, whitelist=whitelist
    )
    filtered_dependency_tree = (
        annotated_dep_tree if tree else filter_dep_tree(annotated_dep_tree)
    )
    Reporter.output(filtered_dependency_tree)
    return filtered_dependency_tree, unknown_licenses


if __name__ == "__main__":
    arguments = docopt(__doc__, version=__version__)

    config_mode = arguments["config"]
    path = arguments["<path>"] or "."
    output = arguments["--output"]
    tree = arguments["--tree"]
    debug = arguments["--debug"]

    config = get_config(path)

    if config_mode:
        config_cmd(path, config)
        exit(0)

    silent = output == "json" or debug

    # docopt guarantees that output variable contains either console or json
    Reporter = {"console": ConsoleReporter, "json": JSONConsoleReporter}[output]

    project_types = get_project_types(path)

    dep_tree = None
    license_map = {}

    if ProjectType.PYTHON_PIPENV in project_types:
        runner = PythonRunner(path, silent, debug)
        dep_tree, license_map = runner.check()

    if ProjectType.NPM in project_types:
        runner = NpmRunner(path, silent, debug)
        dep_tree, license_map = runner.check()

    if ProjectType.MAVEN in project_types:
        runner = MavenRunner(path, silent, debug)
        dep_tree, license_map = runner.check()

    if ProjectType.YARN in project_types:
        runner = YarnRunner(path, silent, debug)
        dep_tree, license_map = runner.check()

    filtered_dep_tree, licenses_not_found = print_dependency_tree_with_licenses(
        dep_tree, config.get("whitelist", [])
    )

    if licenses_not_found and output != "json":
        questions = [
            {
                "type": "confirm",
                "message": "Do you want to add some of the licenses to your whitelist?",
                "name": "continue",
                "default": True,
            }
        ]

        answers = prompt(questions)
        if answers["continue"]:
            questions = [
                {
                    "type": "checkbox",
                    "qmark": "📋",
                    "message": "Whitelist licenses",
                    "name": "whitelist",
                    "choices": [{"name": license} for license in licenses_not_found],
                }
            ]
            answers = prompt(questions)
            if answers["whitelist"]:
                whitelist_licenses(path, answers["whitelist"])

                config = get_config(path)
                filtered_dep_tree, licenses_not_found = print_dependency_tree_with_licenses(
                    dep_tree, config.get("whitelist", [])
                )

    has_issues: bool = filtered_dep_tree.height > 0
    exit(1 if has_issues else 0)
