from ipaserver.plugins import host
from ipalib import _, errors, api, Str
from ipapython.dn import DN
import types

host.host.takes_params = host.host.takes_params + (
    Str('puppetvar*',
      cli_name='puppetvar',
      label=_('puppetVar'),
      doc=_('Puppet variables which are turned into facts on the server'),
    ),
    Str('owner?',
      cli_name='owner',
      label=_('owner'),
      doc=_('Owner or primary user of the machine'),
    ),
)

def normalize_owner(self, owner, ldap, container):
  """
  Given a userid verify the user's existence (in the appropriate containter) and return the dn.
  """
  if not owner:
    return None

  if not isinstance(owner, list):
    owner = [owner]
  try:
    container_dn = DN(container, api.env.basedn)
    for m in xrange(len(owner)):
      if isinstance(owner[m], DN) and owner[m].endswith(container_dn):
        continue
      entry_attrs = ldap.find_entry_by_attr(
        'uid', owner[m], ['posixaccount'], [''],
        container_dn
      )
      owner[m] = entry_attrs.dn
  except errors.NotFound:
    raise errors.NotFound(reason=_('owner %(owner)s not found') % dict(owner=owner[m]))
  return owner

host.host.normalize_owner = types.MethodType(normalize_owner, host, host)

def convert_owner(self, entry_attrs, ldap, **options):
  """
  Convert a owner dn into a userid
  """
  if options.get('raw', False):
    return

  if 'owner' in entry_attrs:
    for m in xrange(len(entry_attrs['owner'])):
      entry_attrs['owner'][m] = ldap.get_entry(entry_attrs['owner'][m], ['uid'])['uid'][0]

host.host.convert_owner = types.MethodType(convert_owner, host, host)

def hostadd_precallback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
  if 'objectclass' not in entry_attrs.keys():
    old_entry = ldap.get_entry(dn, ['objectclass'])
    entry_attrs['objectclass'] = old_entry['objectclass']
  if 'puppetclient' not in entry_attrs['objectclass']:
    entry_attrs['objectclass'].append('puppetclient')
  if 'owner' in entry_attrs:
    entry_attrs['owner'] = self.obj.normalize_owner(entry_attrs['owner'], ldap, 'cn=users,cn=accounts')
  return dn

host.host_add.register_pre_callback(hostadd_precallback)

def hostmod_precallback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
  if 'objectclass' not in entry_attrs.keys():
    old_entry = ldap.get_entry(dn, ['objectclass'])
    entry_attrs['objectclass'] = old_entry['objectclass']
  if 'puppetclient' not in entry_attrs['objectclass']:
    entry_attrs['objectclass'].append('puppetclient')
  if 'owner' in entry_attrs:
    entry_attrs['owner'] = self.obj.normalize_owner(entry_attrs['owner'], ldap, 'cn=users,cn=accounts')
  return dn

host.host_mod.register_pre_callback(hostmod_precallback)

def hostadd_postcallback(self, ldap, dn, entry_attrs, *keys, **options):
  self.obj.convert_owner(entry_attrs, ldap, **options)
  return dn

host.host_add.register_post_callback(hostadd_postcallback)

def hostmod_postcallback(self, ldap, dn, entry_attrs, *keys, **options):
  self.obj.convert_owner(entry_attrs, ldap, **options)
  return dn

host.host_mod.register_post_callback(hostmod_postcallback)

def hostshow_postcallback(self, ldap, dn, entry_attrs, *keys, **options):
  self.obj.convert_owner(entry_attrs, ldap, **options)
  return dn

host.host_show.register_post_callback(hostshow_postcallback)

def hostfind_postcallback(self, ldap, entries, truncated, *args, **options):
  for entry_attrs in entries:
    self.obj.convert_owner(entry_attrs, ldap, **options)
  return truncated

host.host_find.register_post_callback(hostfind_postcallback)