#!/usr/bin/env python3

"""Example main module to see what YASS is capable of."""

import sys
import argparse
from urllib.error import URLError

import yass
from yass.shortcuts import iter_plugins
from yass.logger import logger
from yass.logger import config as logger_config


def collect(domain, excluded_subdomains=None):
    if excluded_subdomains is None:
        excluded_subdomains = list()

    subdomains = list(excluded_subdomains)

    for Plugin in iter_plugins():
        index = 1
        logger().info("Collecting subdomains with {plugin_name}".format(plugin_name=Plugin.__name__))

        try:
            for subdomain in Plugin(domain, exclude_subdomains=subdomains).run():

                if subdomain not in subdomains:
                    subdomains.append(subdomain)

                    logger().info(
                        "\t({index}/{total}) {subdomain}".format(
                            index=index,
                            total=len(subdomains),
                            subdomain=subdomain
                        )
                    )
                    index += 1

        except URLError as e:
            logger().error("Got an unexpected error during connection ({message})".format(message=str(e)))
            logger().warning("Aborting {plugin_name} execution".format(plugin_name=Plugin.__name__))
        except TimeoutError:
            logger().error("Got a timeout error")
            logger().warning("Aborting {plugin_name} execution".format(plugin_name=Plugin.__name__))

    # Remove excluded subdomains from results
    return list(set(subdomains) - set(excluded_subdomains))


def parse(arguments=None):
    parser = argparse.ArgumentParser(prog=yass.__lname__, fromfile_prefix_chars="@", add_help=False)

    class UsageAction(argparse.Action):
        def __call__(self, parser, namespace, values, option_string=None):
            parser.print_usage()
            parser.exit()

    parser.add_argument(dest='domain', metavar='DOMAIN', help="the domain to search for")
    parser.add_argument(dest='excluded_subdomains', metavar='SUBDOMAIN', nargs='*', action="store",
                        help="the list of subdomains to exclude")

    output = parser.add_argument_group('Output arguments')
    output.add_argument('-g', '--grepable', help="output results in grepable format (default: %(default)s)",
                        default=False, action="store_true")
    output.add_argument('-d', '--debug', default=False, action="store_true",
                        help="set output format to a more verbose one, for debugging purpose (default: %(default)s)")
    output.add_argument('-l', '--level', help="set output verbosity (default: %(default)s)",
                        choices=['debug', 'info', 'warning', 'error', 'critical'], default='info')
    color = output.add_mutually_exclusive_group(required=False)
    color.add_argument('-c', '--color', dest="colored", help="use color in the output (default: %(default)s)",
                       action="store_true", default=True)
    color.add_argument('-nc', '--no-color', dest="colored", help="do not use color in the output",
                       action="store_false")

    infos = parser.add_argument_group(title='Informations')
    infos.add_argument('-h', '--help', help="show this help and exit", action="help")
    infos.add_argument('-u', '--usage', help="show the usage and exit", nargs=0, action=UsageAction)
    infos.add_argument('-v', '--version', help="show the framework version an exit", action="version",
                       version="{name} v{version}".format(name=yass.__uname__, version=yass.__version__))

    return parser.parse_args(arguments)


def banner():
    return """
    ________________________________________________

    {name} - {acronym} (v{version})
        by {author}
    ________________________________________________

    """.format(
        name=yass.__uname__,
        acronym=yass.__acronym__,
        version=yass.__version__,
        author=yass.__author__
    )


if __name__ == '__main__':
    if len(sys.argv) == 1:
        sys.argv.append('--usage')

    options = parse(arguments=None)  # Use sys.argv[1:] as default arguments
    if options.grepable:
        options.level = None
    logger_config(options.colored, options.debug, options.level)

    if not options.grepable:
        print(banner())

    subdomains = collect(options.domain, options.excluded_subdomains)
    subdomains.sort()

    if options.grepable:
        print('|'.join(subdomains))
    else:
        if subdomains:
            print(
                "Collected {collected} subdomains\n{subdomains}".format(
                    collected=len(subdomains),
                    subdomains=', '.join(subdomains)
                )
            )
