#!/usr/bin/env python
# encoding=utf8
from __future__ import print_function, absolute_import, division  #, unicode_literals
import objc
import os
import shutil
import sys
from subprocess import Popen, PIPE, check_output

import click

from ._bundle import BAM_PATH, BAM_VERSION
from ._metadata import __version__

BAM_PATH_LEGACY = '/Library/Frameworks/BluetoothAutomation.framework'
__SERVICES_PATH = os.path.join(BAM_PATH, 'Resources', 'Services')
__SERVICES_PATH_LEGACY = os.path.join(BAM_PATH_LEGACY, 'Resources', 'Services')

__BAM_BROKER_FNAME = 'com.apple.bluetoothautomationbroker.plist'
__BAM_ITSELF_FNAME = 'com.apple.bluetoothautomation.plist'
__BAM_AGENT_FNAME = 'com.apple.BluetoothAutomationAgent.plist'

__BAM_BROKER_LAUNCHCTL_SRC = os.path.join(__SERVICES_PATH, __BAM_BROKER_FNAME)
__BAM_ITSELF_LAUNCHCTL_SRC = os.path.join(__SERVICES_PATH, __BAM_ITSELF_FNAME)
__BAM_AGENT_LAUNCHCTL_SRC = os.path.join(__SERVICES_PATH, __BAM_AGENT_FNAME)

__BAM_BROKER_LAUNCHCTL_SRC_LEGACY = os.path.join(__SERVICES_PATH_LEGACY, __BAM_BROKER_FNAME)
__BAM_ITSELF_LAUNCHCTL_SRC_LEGACY = os.path.join(__SERVICES_PATH_LEGACY, __BAM_ITSELF_FNAME)
__BAM_AGENT_LAUNCHCTL_SRC_LEGACY = os.path.join(__SERVICES_PATH_LEGACY, __BAM_AGENT_FNAME)

__USER_LAUNCHCTL_DIR = os.path.expanduser('/AppleInternal/Library/LaunchAgents')
__BAM_BROKER_LAUNCHCTL_DEST = os.path.join(__USER_LAUNCHCTL_DIR, __BAM_BROKER_FNAME)
__BAM_ITSELF_LAUNCHCTL_DEST = os.path.join(__USER_LAUNCHCTL_DIR, __BAM_ITSELF_FNAME)
__BAM_AGENT_LAUNCHCTL_DEST = os.path.join(__USER_LAUNCHCTL_DIR, __BAM_AGENT_FNAME)

__USER_LAUNCHCTL_DIR_LEGACY = os.path.expanduser('~/Library/LaunchAgents')
__BAM_BROKER_LAUNCHCTL_DEST_LEGACY = os.path.join(__USER_LAUNCHCTL_DIR_LEGACY, __BAM_BROKER_FNAME)
__BAM_ITSELF_LAUNCHCTL_DEST_LEGACY = os.path.join(__USER_LAUNCHCTL_DIR_LEGACY, __BAM_ITSELF_FNAME)
__BAM_AGENT_LAUNCHCTL_DEST_LEGACY = os.path.join(__USER_LAUNCHCTL_DIR_LEGACY, __BAM_AGENT_FNAME)

__SRC_DEST_PAIRS = [
    (__BAM_BROKER_LAUNCHCTL_SRC, __BAM_BROKER_LAUNCHCTL_DEST), # 'bluetoothautomationbrokerd'
    (__BAM_ITSELF_LAUNCHCTL_SRC, __BAM_ITSELF_LAUNCHCTL_DEST), # 'bluetoothautomation'
    (__BAM_AGENT_LAUNCHCTL_SRC, __BAM_AGENT_LAUNCHCTL_DEST),   # 'BAMAgent'
    ]

__SRC_DEST_PAIRS_LEGACY = [
    (__BAM_BROKER_LAUNCHCTL_SRC_LEGACY, __BAM_BROKER_LAUNCHCTL_DEST_LEGACY),
    (__BAM_ITSELF_LAUNCHCTL_SRC_LEGACY, __BAM_ITSELF_LAUNCHCTL_DEST_LEGACY),
    (__BAM_AGENT_LAUNCHCTL_SRC_LEGACY, __BAM_AGENT_LAUNCHCTL_DEST_LEGACY),
    ]

# NOTE: gross.  copy-pasta'ed from atk.extras._cli. avoiding adding pyatk depedency to bam.
def was_run_with_sudo():
    """
    Verify the script was run by a regular user using sudo and not just as root.

    Checks the effective UID to determine if script is acting as root, and also checks
    ENV variables, SUDO_UID and SUDO_GID, to verify the script was invoked with sudo.

    :return result: True if script was executed with sudo, False if not
    :rtype: bool
    """
    euid = os.geteuid()
    if euid != 0:
        print('Must be executed by regular user with sudo. try `sudo {}`'.format(' '.join(sys.argv)))
        return False

    # make sure we were elevated to root by checking for some env vars (works for bash and zsh on macOS)
    if not os.environ.get('SUDO_UID') or not os.environ.get('SUDO_GID'):
        print(
            'Are you root? Must be executed by regular user with sudo. Switch to a regular user and try `sudo {}`'.format(
                ' '.join(sys.argv)))
        return False
    return True


@click.group()
def bam():
    """BluetoothAutomation CLI"""


@bam.command()
def version():
    """BAM python package version"""
    click.echo(__version__)


@bam.command()
def framework_version():
    """BluetoothAutomation.framework version"""
    click.echo(BAM_VERSION)


@bam.command()
def activate():
    """Enable BAM launchctl, and start BAM related processes"""
    for plist_src, plist_dest in __SRC_DEST_PAIRS:
        result = Popen(['/bin/launchctl', 'load', '-w', plist_src], stdout=PIPE, stderr=PIPE)
        if not os.path.exists(plist_dest):
            try:
                shutil.copy(plist_src, plist_dest)
            except IOError as e:
                print("Unable to copy file. %s" % e)


@bam.command()
def deactivate():
    """Disable BAM launchctl, and stop BAM related processes"""
    for plist_src, plist_dest in __SRC_DEST_PAIRS:
        # persistent unload
        result = Popen(['/bin/launchctl', 'unload', '-w', plist_src], stdout=PIPE, stderr=PIPE)

    # unload and remove legacy BAM services
    for plist_src, plist_dest in __SRC_DEST_PAIRS_LEGACY:
        result = Popen(['/bin/launchctl', 'unload', '-w', plist_src], stdout=PIPE, stderr=PIPE)
        if os.path.exists(plist_dest):
            os.remove(plist_dest)


@bam.group()
def debug():
    """Debug commands. DANGER ZONE."""


@debug.command()
def expunge():
    """Disable BAM launctl, stop the BAM related processes, and delete BAM related launchctl plists."""
    for plist_src, plist_dest in __SRC_DEST_PAIRS:
        # persistent unload
        result = Popen(['/bin/launchctl', 'unload', '-w', plist_dest], stdout=PIPE, stderr=PIPE)
        # kill the file
        os.remove(plist_dest)


@bam.group()
def btkiller():
    """Configure bluetooth host controller switch behavior."""


# TODO: btkiller activate and deactivate commands are BASICALLY the same. should rely on single implementation.
@btkiller.command()
def activate():
    """Overwrite the default HCI behavior to not use internal bluetooth."""
    if not was_run_with_sudo():
        raise click.Abort('bam debug uninstall-framework must be run with sudo')
    result = Popen(['/usr/sbin/nvram', 'bluetoothHostControllerSwitchBehavior=never'], stdout=PIPE, stderr=PIPE)
    out, err = result.communicate()
    if result.returncode == 0:
        click.echo('nvram bluetoothHostControllerSwitchBehavior set to never. Reboot required to take effect.')
        # TODO:
    else:
        click.echo('failed to set nvram bluetoothHostControllerSwitchBehavior=never. stdout: {}, stderr: {}'.format(
            result.stdout.read(),
            result.stderr.read(),
        ))


@btkiller.command()
def deactivate():
    """Reset the default HCI behavior to use internal bluetooth."""
    if not was_run_with_sudo():
        raise click.Abort('bam debug uninstall-framework must be run with sudo')
    # sudo nvram -d bluetoothHostControllerSwitchBehavior
    result = Popen(['/usr/sbin/nvram', 'bluetoothHostControllerSwitchBehavior=always'], stdout=PIPE, stderr=PIPE)
    out, err = result.communicate()
    if result.returncode == 0:
        click.echo('nvram bluetoothHostControllerSwitchBehavior set to always. Reboot required to take effect.')
        # TODO:
    else:
        click.echo('failed to set nvram bluetoothHostControllerSwitchBehavior=always. stdout: {}, stderr: {}'.format(
            result.stdout.read(),
            result.stderr.read(),
        ))