# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models
from django.core.validators import MaxValueValidator
from django.core.exceptions import ValidationError

from coin.members.models import count_active_members
from coin.offers.models import count_active_subscriptions

# API version, see http://db.ffdn.org/format
API_VERSION = "0.1"

TECHNOLOGIES = (('ftth', 'FTTH'),
                ('dsl', '*DSL'),
                ('wifi', 'WiFi'))


class SingleInstanceMixin(object):
    """Makes sure that no more than one instance of a given model is created."""

    def clean(self):
        model = self.__class__
        if (model.objects.count() > 0 and self.id != model.objects.get().id):
            raise ValidationError("Can only create 1 instance of %s" % model.__name__)
        super(SingleInstanceMixin, self).clean()


class ISPInfo(SingleInstanceMixin, models.Model):
    """http://db.ffdn.org/format

    The naming convention is different from Python/django so that it
    matches exactly the format (which uses CamelCase...)
    """
    name = models.CharField(max_length=512,
                            help_text="The ISP's name")
    # Length required by the spec
    shortname = models.CharField(max_length=15, blank=True,
                                 help_text="Shorter name")
    description = models.TextField(blank=True,
                                   help_text="Short text describing the project")
    logoURL = models.URLField(blank=True,
                              verbose_name="logo URL",
                              help_text="HTTP(S) URL of the ISP's logo")
    website = models.URLField(blank=True,
                              help_text='URL to the official website')
    email = models.EmailField(max_length=254,
                              help_text="Contact email address")
    mainMailingList = models.EmailField(max_length=254, blank=True,
                                        verbose_name="main mailing list",
                                        help_text="Main public mailing-list")
    creationDate = models.DateField(blank=True, null=True,
                                    verbose_name="creation date",
                                     help_text="Date of creation for legal structure")
    ffdnMemberSince = models.DateField(blank=True, null=True,
                                       verbose_name="FFDN member since",
                                       help_text="Date at wich the ISP joined the Federation")
    # TODO: choice field
    progressStatus = models.PositiveSmallIntegerField(
        validators=[MaxValueValidator(7)],
        blank=True, null=True, verbose_name='progress status',
        help_text="Progression status of the ISP")
    # TODO: better model for coordinates
    latitude = models.FloatField(blank=True, null=True,
        help_text="Coordinates of the registered office (latitude)")
    longitude = models.FloatField(blank=True, null=True,
        help_text="Coordinates of the registered office (longitude)")

    # Uncomment this if you want to manage these counters by hand.
    #member_count = models.PositiveIntegerField(help_text="Number of members")
    #subscriber_count = models.PositiveIntegerField(
    #    help_text="Number of subscribers to an internet access")

    @property
    def memberCount(self):
        """Number of members"""
        return count_active_members()

    @property
    def subscriberCount(self):
        """Number of subscribers to an internet access"""
        return count_active_subscriptions()

    @property
    def version(self):
        """Version of the API"""
        return API_VERSION

    def get_absolute_url(self):
        return '/isp.json'

    def to_dict(self):
        data = dict()
        # These are required
        for f in ('version', 'name', 'email', 'memberCount', 'subscriberCount'):
            data[f] = getattr(self, f)

        # These are optional
        for f in ('shortname', 'description', 'logoURL', 'website',
                  'mainMailingList', 'progressStatus'):
            if getattr(self, f):
                data[f] = getattr(self, f)

        # Dates
        for d in ('creationDate', 'ffdnMemberSince'):
            if getattr(self, d):
                data[d] = getattr(self, d).isoformat()

        # Hackish for now
        if self.latitude or self.longitude:
            data['coordinates'] = { "latitude": self.latitude,
                                    "longitude": self.longitude }

        # Related objects
        data['coveredAreas'] = [c.to_dict() for c in self.coveredarea_set.all()]
        otherwebsites = self.otherwebsite_set.all()
        if otherwebsites:
            data['otherWebsites'] = { site.name: site.url for site in otherwebsites }
        chatrooms = self.chatroom_set.all()
        if chatrooms:
            data['chatrooms'] = [chatroom.url for chatroom in chatrooms]
        if hasattr(self, 'registeredoffice'):
            data['registeredOffice'] = self.registeredoffice.to_dict()

        return data

    def __unicode__(self):
        return self.name


class OtherWebsite(models.Model):
    name = models.CharField(max_length=512)
    url = models.URLField(verbose_name="URL")
    isp = models.ForeignKey(ISPInfo)


class RegisteredOffice(models.Model):
    """ http://json-schema.org/address """
    post_office_box = models.CharField(max_length=512, blank=True)
    extended_address = models.CharField(max_length=512, blank=True)
    street_address = models.CharField(max_length=512, blank=True)
    locality = models.CharField(max_length=512)
    region = models.CharField(max_length=512)
    postal_code = models.CharField(max_length=512, blank=True)
    country_name = models.CharField(max_length=512)
    isp = models.OneToOneField(ISPInfo)

    def to_dict(self):
        d = dict()
        for field in ('post_office_box', 'extended_address', 'street_address',
                      'locality', 'region', 'postal_code', 'country_name'):
            if getattr(self, field):
                key = field.replace('_', '-')
                d[key] = getattr(self, field)
        return d


class ChatRoom(models.Model):
    url = models.CharField(verbose_name="URL", max_length=256)
    isp = models.ForeignKey(ISPInfo)


class CoveredArea(models.Model):
    name = models.CharField(max_length=512)
    # TODO: we must allow multiple values
    technologies = models.CharField(choices=TECHNOLOGIES, max_length=16)
    # TODO: find a geojson library
    #area =
    isp = models.ForeignKey(ISPInfo)

    def to_dict(self):
        return {"name": self.name,
                "technologies": [self.technologies]}
