#!/usr/bin/env python3
import configparser
import getpass
import os
import shutil
import subprocess
import sys
import argparse

import pkg_resources

try:
    import raveberry

    raveberry_directory = os.path.dirname(raveberry.__file__)
    default_config = os.path.join(raveberry_directory, "config/raveberry.ini")
except ModuleNotFoundError:
    # also allow this script to work without installed module in the git folder
    raveberry_directory = "."
    default_config = os.path.join(raveberry_directory, "config/raveberry.ini")

used_config = default_config


def main():
    parser = argparse.ArgumentParser(
        description="""\
    A multi-user music server with a focus on participation.
    For more info visit https://github.com/raveberry/raveberry""",
        formatter_class=argparse.RawTextHelpFormatter,
    )
    parser.add_argument(
        "command",
        help="""\
    run             run a basic version of raveberry
    system-install  install raveberry into the system
    version         print the version of this module
    help            show this help and exit""",
    )
    parser.add_argument(
        "--config-file",
        "-c",
        type=str,
        help="Specify a config file to use for system-install",
    )
    parser.add_argument(
        "--confirm-config",
        action="store_true",
        help="Do not prompt to confirm the config file",
    )
    args = parser.parse_args()

    if args.config_file:
        global used_config
        used_config = os.path.abspath(args.config_file)

    os.chdir(raveberry_directory)
    command = args.command.lstrip("-")
    choices = ["run", "system-install", "version", "v"]
    if command not in choices:
        parser.print_help()
        sys.exit(1)
    elif command == "run":
        run_server()
    elif command == "system-install":
        system_install(config_confirmed=args.confirm_config)
    elif command == "version" or command == "v":
        version()
    else:
        print("unknown command")
        sys.exit(1)


def version():
    try:
        print(pkg_resources.require("raveberry")[0].version)
    except pkg_resources.DistributionNotFound:
        print("raveberry is not currently installed")
        sys.exit(1)


def run_server():
    if not os.path.isfile("db.sqlite3"):
        print("first time running raveberry, preparing...")
        user_install()
    print("This is the basic raveberry version using a debug server.")
    print("To install with all features run `raveberry system-install`")
    try:
        subprocess.check_call(f"pgrep mopidy".split(), stdout=subprocess.DEVNULL)
    except subprocess.CalledProcessError:
        print("mopidy not yet running, starting...")
        subprocess.Popen(["mopidy"], stderr=subprocess.DEVNULL)
    subprocess.call(["scripts/runserver.sh"])


def read_config():
    config = configparser.ConfigParser()
    config.read(used_config)
    for section_name, section in config.items():
        for key, value in section.items():
            try:
                enabled = config.getboolean(section_name, key)
            except ValueError:
                enabled = True
            if enabled:
                os.environ[key.upper()] = value


def user_install():
    apt_packages = ["python3-pip", "ffmpeg", "atomicparsley", "mopidy", "redis-server"]
    missing_packages = []

    if shutil.which("dpkg"):
        for package in apt_packages:
            try:
                subprocess.check_call(
                    f"dpkg -s {package}".split(),
                    stdout=subprocess.DEVNULL,
                    stderr=subprocess.DEVNULL,
                )
            except subprocess.CalledProcessError:
                missing_packages.append(package)
        if missing_packages:
            print(
                "please install missing packages: sudo apt-get install -y "
                + " ".join(missing_packages)
            )
            sys.exit(1)
    else:
        print(
            "Warning: dpkg is not installed, could not check if dependencies are installed! Use at your own risk!"
        )

    read_config()
    subprocess.call(["/bin/bash", "setup/user_install.sh"])


def system_install(config_confirmed=False):
    print(
        """You are about to install raveberry system-wide. This will make it start on boot and enable features specified in the config file.
Depending on your configuration, this will alter some system files. (Although everything *should* work fine, backups are recommended)
Config-file location: """
        + used_config
    )

    if not config_confirmed:
        answer = input(
            "Is this the configuration you want to install raveberry with? [Y/n] "
        )
        while answer not in ["", "Y", "y", "Yes", "yes", "N", "n", "No", "no"]:
            answer = input('Please answers "yes" or "no": ')
        if answer in ["N", "n", "No", "no"]:
            sys.exit(0)

    if used_config != default_config:
        # If the user provided a different config, copy it to the default config's location,
        # so it is available for upgrades after the install.
        shutil.copyfile(used_config, default_config)

    read_config()

    db_exists = not subprocess.call(
        'sudo -u postgres psql -lqt | cut -d \\| -f 1 | grep -qw "raveberry"',
        shell=True,
        stderr=subprocess.DEVNULL,
    )
    if os.environ["DB_BACKUP"] or db_exists:
        # another database is already present, do not ask for a new admin password
        pass
    else:
        while True:
            admin_password = getpass.getpass("Set admin password: ")
            admin_password_confirmed = getpass.getpass("Confirm admin password: ")
            if admin_password == admin_password_confirmed:
                os.environ["ADMIN_PASSWORD"] = admin_password
                break
            print("Passwords didn't match")
    subprocess.call(["sudo", "-E", "/bin/bash", "setup/setup.sh"])


if __name__ == "__main__":
    main()
