text: # -*- coding: utf-8 -*-
  '''
  This module allows you to manage assistive access on macOS minions with 10.9+
  
  .. versionadded:: 2016.3.0
  
  .. code-block:: bash
  
      salt '*' assistive.install /usr/bin/osascript
  '''
  
  # Import Python Libs
  from __future__ import absolute_import, unicode_literals, print_function
  import re
  import logging
  
  # Import salt libs
  import salt.utils.platform
  import salt.utils.stringutils
  from salt.exceptions import CommandExecutionError
  from salt.utils.versions import LooseVersion as _LooseVersion
  
  log = logging.getLogger(__name__)
  
  __virtualname__ = 'assistive'
  
  
  def __virtual__():
      '''
      Only work on Mac OS
      '''
      if salt.utils.platform.is_darwin() \
              and _LooseVersion(__grains__['osrelease']) >= '10.9':
          return True
      return (
          False,
          'The assistive module cannot be loaded: must be run on '
          'macOS 10.9 or newer.'
      )
  
  
  def install(app_id, enable=True):
      '''
      Install a bundle ID or command as being allowed to use
      assistive access.
  
      app_id
          The bundle ID or command to install for assistive access.
  
      enabled
          Sets enabled or disabled status. Default is ``True``.
  
      CLI Example:
  
      .. code-block:: bash
  
          salt '*' assistive.install /usr/bin/osascript
          salt '*' assistive.install com.smileonmymac.textexpander
      '''
      ge_el_capitan = True if _LooseVersion(__grains__['osrelease']) >= salt.utils.stringutils.to_str('10.11') else False
      client_type = _client_type(app_id)
      enable_str = '1' if enable else '0'
      cmd = 'sqlite3 "/Library/Application Support/com.apple.TCC/TCC.db" ' \
            '"INSERT or REPLACE INTO access VALUES(\'kTCCServiceAccessibility\',\'{0}\',{1},{2},1,NULL{3})"'.\
          format(app_id, client_type, enable_str, ',NULL' if ge_el_capitan else '')
  
      call = __salt__['cmd.run_all'](
          cmd,
          output_loglevel='debug',
          python_shell=False
      )
      if call['retcode'] != 0:
          comment = ''
          if 'stderr' in call:
              comment += call['stderr']
          if 'stdout' in call:
              comment += call['stdout']
  
          raise CommandExecutionError('Error installing app: {0}'.format(comment))
  
      return True
  
  
  def installed(app_id):
      '''
      Check if a bundle ID or command is listed in assistive access.
      This will not check to see if it's enabled.
  
      app_id
          The bundle ID or command to check installed status.
  
      CLI Example:
  
      .. code-block:: bash
  
          salt '*' assistive.installed /usr/bin/osascript
          salt '*' assistive.installed com.smileonmymac.textexpander
      '''
      for a in _get_assistive_access():
          if app_id == a[0]:
              return True
  
      return False
  
  
  def enable(app_id, enabled=True):
      '''
      Enable or disable an existing assistive access application.
  
      app_id
          The bundle ID or command to set assistive access status.
  
      enabled
          Sets enabled or disabled status. Default is ``True``.
  
      CLI Example:
  
      .. code-block:: bash
  
          salt '*' assistive.enable /usr/bin/osascript
          salt '*' assistive.enable com.smileonmymac.textexpander enabled=False
      '''
      enable_str = '1' if enabled else '0'
      for a in _get_assistive_access():
          if app_id == a[0]:
              cmd = 'sqlite3 "/Library/Application Support/com.apple.TCC/TCC.db" ' \
                    '"UPDATE access SET allowed=\'{0}\' WHERE client=\'{1}\'"'.format(enable_str, app_id)
  
              call = __salt__['cmd.run_all'](
                  cmd,
                  output_loglevel='debug',
                  python_shell=False
              )
  
              if call['retcode'] != 0:
                  comment = ''
                  if 'stderr' in call:
                      comment += call['stderr']
                  if 'stdout' in call:
                      comment += call['stdout']
  
                  raise CommandExecutionError('Error enabling app: {0}'.format(comment))
  
              return True
  
      return False
  
  
  def enabled(app_id):
      '''
      Check if a bundle ID or command is listed in assistive access and
      enabled.
  
      app_id
          The bundle ID or command to retrieve assistive access status.
  
      CLI Example:
  
      .. code-block:: bash
  
          salt '*' assistive.enabled /usr/bin/osascript
          salt '*' assistive.enabled com.smileonmymac.textexpander
      '''
      for a in _get_assistive_access():
          if app_id == a[0] and a[1] == '1':
              return True
  
      return False
  
  
  def remove(app_id):
      '''
      Remove a bundle ID or command as being allowed to use assistive access.
  
      app_id
          The bundle ID or command to remove from assistive access list.
  
      CLI Example:
  
      .. code-block:: bash
  
          salt '*' assistive.remove /usr/bin/osascript
          salt '*' assistive.remove com.smileonmymac.textexpander
      '''
      cmd = 'sqlite3 "/Library/Application Support/com.apple.TCC/TCC.db" ' \
            '"DELETE from access where client=\'{0}\'"'.format(app_id)
      call = __salt__['cmd.run_all'](
          cmd,
          output_loglevel='debug',
          python_shell=False
      )
  
      if call['retcode'] != 0:
          comment = ''
          if 'stderr' in call:
              comment += call['stderr']
          if 'stdout' in call:
              comment += call['stdout']
  
          raise CommandExecutionError('Error removing app: {0}'.format(comment))
  
      return True
  
  
  def _client_type(app_id):
      '''
      Determine whether the given ID is a bundle ID or a
      a path to a command
      '''
      return '1' if app_id[0] == '/' else '0'
  
  
  def _get_assistive_access():
      '''
      Get a list of all of the assistive access applications installed,
      returns as a ternary showing whether each app is enabled or not.
      '''
      cmd = 'sqlite3 "/Library/Application Support/com.apple.TCC/TCC.db" "SELECT * FROM access"'
      call = __salt__['cmd.run_all'](
          cmd,
          output_loglevel='debug',
          python_shell=False
      )
  
      if call['retcode'] != 0:
          comment = ''
          if 'stderr' in call:
              comment += call['stderr']
          if 'stdout' in call:
              comment += call['stdout']
  
          raise CommandExecutionError('Error: {0}'.format(comment))
  
      out = call['stdout']
      return re.findall(r'kTCCServiceAccessibility\|(.*)\|[0-9]{1}\|([0-9]{1})\|[0-9]{1}\|', out, re.MULTILINE)
  