#!/usr/bin/env python
"""Executable script for running statick against a workspace."""

from __future__ import print_function

import os
import sys

from statick_tool.args import Args
from statick_tool.package import Package
from statick_tool.plugin_context import PluginContext
from statick_tool.statick import Statick


def main():  # pylint: disable=too-many-locals, too-many-branches, too-many-statements
    """Run statick_ws."""
    args = Args("Statick workspace tool")
    args.parser.add_argument("path", help="Path of workspace to scan")
    args.parser.add_argument("--packages-file", dest="packages_file", type=str,
                             help="File listing packages to scan")
    args.parser.add_argument("--list-packages", dest="list_packages",
                             action="store_true", help="List packages and levels")

    statick = Statick(args.get_user_paths())
    statick.gather_args(args.parser)
    parsed_args = args.get_args()
    statick.get_config(parsed_args)
    statick.get_exceptions(parsed_args)

    out_dir = parsed_args.output_directory
    if not os.path.isdir(out_dir):
        print("Output directory not found at " + out_dir + "!")
        sys.exit(1)

    ignore_packages = statick.get_ignore_packages()

    packages = []
    for root, dirs, files in os.walk(parsed_args.path):
        for sub_dir in dirs:
            full_dir = os.path.join(root, sub_dir)
            files = os.listdir(full_dir)
            if "CMakeLists.txt" in files and "CATKIN_IGNORE" not in files and \
                    "AMENT_IGNORE" not in files and "package.xml" in files:
                if ignore_packages and sub_dir in ignore_packages:
                    continue
                packages.append((sub_dir, full_dir))

    if parsed_args.packages_file is not None:
        packages_file_list = []
        try:
            packages_file = os.path.abspath(parsed_args.packages_file)
            with open(packages_file, "r") as fname:
                packages_file_list = [package.strip() for package
                                      in fname.readlines()
                                      if package.strip() and
                                      package[0] != "#"]
        except IOError:
            print("Packages file not found")
            sys.exit(1)
        packages = [package for package in packages if package[0] in packages_file_list]

    count = 0
    total_issues = []
    issues = {}
    for package in packages:
        if parsed_args.list_packages:
            print("%-40s: %s" % (package[0], statick.get_level(package[1], parsed_args)))
            continue

        count += 1
        print("-- Scanning package " + package[0] + " (" + str(count) +
              " of " + str(len(packages)) + ") --")
        issues, dummy = statick.run(package[1], parsed_args)
        if issues is not None:
            total_issues.append(issues)
        else:
            print("Failed to run statick on package " + package[0] + "!")
            sys.exit(1)
        print("-- Done scanning package " + package[0] + " (" + str(count) +
              " of " + str(len(packages)) + ") --")

    if parsed_args.list_packages:
        sys.exit(0)

    print("-- All packages run --")
    print("-- overall report --")

    for issue in total_issues:
        for key, value in list(issue.items()):
            if key in issues:
                issues[key] += value
            else:
                issues[key] = value

    # Make a fake 'all' package for reporting
    dummy_all_package = Package('all_packages', parsed_args.path)
    level = statick.get_level(dummy_all_package.path, parsed_args)
    enabled_reporting_plugins = statick.config.get_enabled_reporting_plugins(level)
    available_reporting_plugins = {}
    for plugin_info in statick.manager.getPluginsOfCategory("Reporting"):
        available_reporting_plugins[plugin_info.plugin_object.get_name()] = \
            plugin_info.plugin_object

    # Make a dummy plugincontext as well
    plugin_context = PluginContext(args, None, None)
    plugin_context.args.output_directory = parsed_args.output_directory

    if not enabled_reporting_plugins:
        enabled_reporting_plugins = list(available_reporting_plugins)

    for plugin_name in enabled_reporting_plugins:
        if plugin_name not in available_reporting_plugins:
            print("Can't find specified reporting plugin {}!".format(plugin_name))
        plugin = statick.reporting_plugins[plugin_name]
        plugin.set_plugin_context(plugin_context)
        print("Running {} reporting plugin...".format(plugin.get_name()))
        plugin.report(dummy_all_package, issues, level)
        print("{} reporting plugin done.".format(plugin.get_name()))


if __name__ == "__main__":
    main()
