#!/usr/bin/env python3

import argparse
import glob
import logging
import os
import subprocess
import sys
from typing import Iterator


def get_bot_paths() -> Iterator[str]:
    current_dir = os.path.dirname(os.path.abspath(__file__))
    bots_dir = os.path.join(current_dir, "bots")
    bots_subdirs = map(lambda d: os.path.abspath(d), glob.glob(bots_dir + "/*"))
    paths = filter(lambda d: os.path.isdir(d), bots_subdirs)
    return paths


def provision_bot(path_to_bot: str, force: bool) -> None:
    req_path = os.path.join(path_to_bot, "requirements.txt")
    if os.path.isfile(req_path):
        bot_name = os.path.basename(path_to_bot)
        logging.info(f"Installing dependencies for {bot_name}...")

        # pip install -r $BASEDIR/requirements.txt -t $BASEDIR/bot_dependencies --quiet
        rcode = subprocess.call(["pip", "install", "-r", req_path])

        if rcode != 0:
            logging.error("Error. Check output of `pip install` above for details.")
            if not force:
                logging.error("Use --force to try running anyway.")
                sys.exit(rcode)  # Use pip's exit code
        else:
            logging.info("Installed dependencies successfully.")


def parse_args(available_bots: Iterator[str]) -> argparse.Namespace:
    usage = """
Installs dependencies of bots in the bots/<bot_name>
directories. Add a requirements.txt file in a bot's folder
before provisioning.

To provision all bots, use:
./provision.py

To provision specific bots, use:
./provision.py [names of bots]
Example: ./provision.py helloworld xkcd wikipedia
"""
    parser = argparse.ArgumentParser(usage=usage)

    parser.add_argument(
        "bots_to_provision",
        metavar="bots",
        nargs="*",
        default=available_bots,
        help="specific bots to provision (default is all)",
    )

    parser.add_argument(
        "--force",
        default=False,
        action="store_true",
        help="Continue installation despite pip errors.",
    )

    parser.add_argument(
        "--quiet", "-q", action="store_true", default=False, help="Turn off logging output."
    )

    return parser.parse_args()


def main() -> None:
    options = parse_args(available_bots=get_bot_paths())

    if not options.quiet:
        logging.basicConfig(stream=sys.stdout, level=logging.INFO)

    for bot in options.bots_to_provision:
        provision_bot(bot, options.force)


if __name__ == "__main__":
    main()
