# Copyright 2014 Budapest University of Technology and Economics (BME IK)
#
# This file is part of CIRCLE Cloud.
#
# CIRCLE is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# CIRCLE is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE.  If not, see <http://www.gnu.org/licenses/>.
import openstack_api
from django.conf import settings
from django.contrib.auth import user_logged_in
from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator
from django.core.urlresolvers import reverse
from django.db.models import CharField
from django.utils.translation import ugettext_lazy as _
from django.contrib.contenttypes.fields import (
    GenericRelation, GenericForeignKey
)
from django.contrib.contenttypes.models import ContentType

from firewall.models import Vlan
from firewall.fields import val_alfanum
from openstack_auth.user import User


class EditorElement(models.Model):
    x = models.IntegerField()
    y = models.IntegerField()
    free_port_num = models.IntegerField()
    owner = models.ForeignKey(User)

    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey()

    def as_data(self):
        type = 'network' if isinstance(self.content_object, Vxlan) else 'vm'
        if type == 'network':
            id = "net-%s" % self.content_object.vni
        else:
            id = "vm-%s" % self.content_object.pk
        return {
            'name': unicode(self.content_object),
            'id': id,
            'x': self.x,
            'y': self.y,
            'free_port_num': self.free_port_num,
            'type': type,
            'description': self.content_object.description,
        }


class Vxlan(models.Model):

    """
    A virtual L2 network,
    """
    os_network_id = CharField(blank=False, max_length=100, unique=True)
    editor_elements = GenericRelation(EditorElement)

    class Meta:
        app_label = 'network'

    @classmethod
    def list_from_os(cls, request):
        return openstack_api.neutron.network_list_for_tenant(request, request.user.tenant_id)

    def __unicode__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('network.vxlan', kwargs={'vni': self.vni})

class SubnetPool(object):
    @classmethod
    def get(cls, request):
        subnet_pools = openstack_api.neutron.subnetpool_list(request)
        subnet_pools = [sp for sp in subnet_pools if sp.name == settings.DEFAULT_SUBNETPOOL_NAME_FOR_USER]
        return subnet_pools[0] if len(subnet_pools) > 0 else None

    @classmethod
    def create_if_not_exists(cls, sender, user, request, **kwargs):
        if SubnetPool.get(request) is None:
            openstack_api.neutron.subnetpool_create(
                request,
                settings.DEFAULT_SUBNETPOOL_NAME_FOR_USER,
                settings.DEFAULT_SUBNETPOOL_PREFIXES,
                default_prefixlen=settings.DEFAULT_SUBNETPOOL_PREFIX_LEN
            )

    @classmethod
    def get_id(cls, request):
        return SubnetPool.get(request).id

user_logged_in.connect(SubnetPool.create_if_not_exists)
