from django.db import models
from django.http import HttpResponse
from passerelle.base.models import BaseResource
from passerelle.utils.jsonresponse import APIError

import jsonfield

from .utils import base


#TODO
# derive CsvDataSource connector
# default connexion values for CreateView
# read py files in passerelle/base/

CHOICES = (('1', 'BASE',), ('2', 'LEVEL',), ('3', 'SUBTREE',))
OPERATIONS = (('1', 'Search',), ('2', 'Add',), ('3', 'Modify',), ('4', 'Delete',), ('5', 'LDIF',))

# Create your models here.
def format_person(p):
    data = {} #TODO format to LDAP InetOrgPerson schema?
    return data

def format_org_unit(u):
    data = {}
    return data

def get_org_unit(u):
    return 0

class LDAPResource(BaseResource):
    # XXX normalize max_length values
    #ldif_file = models.FileField('LDIF File', upload_to='ldif', blank=True) # For future uses
    server = models.CharField('Server name', max_length=200, default='localhost')
    user = models.CharField('Username (full DN)', max_length=200, blank=True)
    password = models.CharField('Password', max_length=50, blank=True)

    _dialect_options = jsonfield.JSONField(editable=False, null=True) #FIXME

    category = 'Identity Management Connectors'
    class Meta:
        verbose_name = 'LDAP_DIR'

    def get(self, request, *args, **kwargs):
        return HttpResponse("Dummy response view")


    @classmethod
    def get_icon_class(cls):
        return 'grid'

    @classmethod
    def get_verbose_name(cls):
        return "LDAP Connector v3"

    @classmethod
    def is_enabled(cls):
        return True

    def clean(self, *args, **kwargs):
        #TODO
        return super(LDAPResource, self).clean(*args, **kwargs)

    def save(self, *args, **kwargs):
        #TODO
        return super(LDAPResource, self).save(*args, **kwargs)

    @property
    def dialect_options(self): #FIXME
        """turn dict items into string
        """
        # Set dialect_options if None
        if self._dialect_options is None:
            self.save()

        options = {}
        for k, v in self._dialect_options.items():
            if isinstance(v, unicode):
                v = v.encode('ascii')
            options[k.encode('ascii')] = v

        return options

    def get_content_without_bom(self): # Useless here?
        self.ldif_file.seek(0)
        content = self.ldif_file.read()
        return content.decode('utf-8-sig', 'ignore').encode('utf-8')

    def select(self, request, query_name, **kwargs):
        try:
            Query.objects.get(resource=self.id, slug=query_name)
        except Query.DoesNotExist:
            raise APIError(u'no such query')

## TODO
class GenericOperation(models.Model):
    foo = models.TextField()

class AddOperation(models.Model):
    distinguished_name = models.TextField('Distinguished name', blank=True, default=base,
            help_text='Distinguished name for the \'Add\' operation')
    object_class = models.TextField('Object class(es)', blank=True,
            help_text='List of object classes')
    attributes = models.TextField('Attributes', blank=True,
            help_text='Dictionary of attributes for the new entry')
    controls = models.TextField('Controls', blank=True,
            help_text='Optional request control parameters (see ldap3 doc)')

class DeleteOperation(models.Model):
    distinguished_name = models.TextField('Distinguished name', blank=True, default=base,
            help_text='Distinguished name for the \'Delete\' operation')
    controls = models.TextField('Controls', blank=True,
            help_text='Optional request control parameters (see ldap3 doc)')

class ModifyOperation(models.Model):
    distinguished_name = models.TextField('Distinguished name', blank=True, default=base,
            help_text='Distinguished name for the \'Modify\' operation')
    changes = models.TextField('Changes', blank=True,
            help_text='Dictionary of changes for the modified entry')
    controls = models.TextField('Controls', blank=True,
            help_text='Optional request control parameters (see ldap3 doc)')

class ModifyDNOperation(models.Model):
    distinguished_name = models.TextField('Distinguished name', blank=True, default=base,
            help_text='Distinguished name for the \'ModifyDN\' operation')
    relative_dn = models.TextField('Relative distinguished name', blank=True, default=base,
            help_text='Relative distinguished name for the \'ModifyDN\' operation')
    delete_old_dn = models.BooleanField('Delete old DN?', default=True)
    new_superior = models.TextField('New superior', blank=True, default=base,
            help_text='New container for the entry')
    controls = models.TextField('Controls', blank=True,
            help_text='Optional request control parameters (see ldap3 doc)')


class Query(models.Model):
    resource = models.ForeignKey(LDAPResource)
    slug = models.SlugField('Name (slug)')
    label = models.CharField('Label', max_length=100)
    description = models.TextField('Description', blank=True)
    #server = models.CharField('Server', max_length=200)
    #user = models.CharField('User', max_length=200)
    #password = models.CharField('Password', max_length=50)
    ldif_file = models.FileField('LDIF File', upload_to='ldif', blank=True) # For future uses
    distinguished_name = models.TextField('Distinguished name', blank=True, default=base,
            help_text='Distinguished name for the LDAP operation')
    filters = models.TextField('Filters', blank=True,
            help_text='List of filter clauses (LDAP RFC4515 expression)')
    attributes = models.TextField('Attributes', blank=False, default='ALL_ATTRIBUTES',
            help_text='List of attributes to retrieve for matching entries.')
    scope = models.CharField('Scope', choices=CHOICES, max_length=1,
            blank=False, default='1')
    operation = models.CharField('Operation type', choices=OPERATIONS, max_length=1,
            blank=False, default='1')

    #projections = models.TextField('Projections', blank=True,
    #        help_text='List of projections (name:expression)')
    #order = models.TextField('Order', blank=True,
    #        help_text='Ordering columns')
    #distinct = models.TextField('Distinct', blank=True,
    #        help_text='Distinct columns')
    #structure = models.CharField('Structure',
    #        max_length=20,
    #        choices=[
    #            ('array', 'Array'),
    #            ('dict', 'Dictionary'),
    #            ('tuples', 'Tuples'),
    #            ('onerow', 'Single Row'),
    #            ('one', 'Single Value')],
    #        default='dict',
    #        help_text='Data structure used for the response')

    class Meta:
        ordering = ['slug']

    def get_list(self, attribute):
        if not getattr(self, attribute):
            return []
        return getattr(self, attribute).strip().splitlines()
