# 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/>.

from collections import OrderedDict

from netaddr import IPNetwork
from django.views.generic import (TemplateView, UpdateView, DeleteView,
                                  CreateView)
from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse_lazy
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse, Http404
from django.db.models import Q

from django_tables2 import SingleTableView

from firewall.models import (
    Host, Vlan, Domain, Group, Record, BlacklistItem, Rule, VlanGroup,
    SwitchPort, EthernetDevice, Firewall)
from vm.models import Interface
from .tables import (
    HostTable, VlanTable, SmallHostTable, DomainTable, GroupTable,
    RecordTable, BlacklistItemTable, RuleTable, VlanGroupTable,
    SmallRuleTable, SmallGroupRuleTable, SmallRecordTable, SwitchPortTable,
    SmallDhcpTable, FirewallTable, FirewallRuleTable,
)
from .forms import (
    HostForm, VlanForm, DomainForm, GroupForm, RecordForm, BlacklistItemForm,
    RuleForm, VlanGroupForm, SwitchPortForm, FirewallForm
)

from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.edit import FormMixin
from django.utils.translation import ugettext_lazy as _
from braces.views import LoginRequiredMixin, SuperuserRequiredMixin
# from django.db.models import Q
from operator import itemgetter
from itertools import chain
from dashboard.views import AclUpdateView
from dashboard.forms import AclUserOrGroupAddForm

try:
    from django.http import JsonResponse
except ImportError:
    from django.utils import simplejson

    class JsonResponse(HttpResponse):
        """JSON response for Django < 1.7
        https://gist.github.com/philippeowagner/3179eb475fe1795d6515
        """
        def __init__(self, content, mimetype='application/json',
                     status=None, content_type=None):
            super(JsonResponse, self).__init__(
                content=simplejson.dumps(content),
                mimetype=mimetype,
                status=status,
                content_type=content_type)


class MagicMixin(object):

    def get(self, *args, **kwargs):
        if self.request.is_ajax():
            result = self._get_ajax(*args, **kwargs)
            return JsonResponse({k: unicode(result[k] or "") for k in result})
        else:
            return super(MagicMixin, self).get(*args, **kwargs)


class InitialOwnerMixin(FormMixin):
    def get_initial(self):
        initial = super(InitialOwnerMixin, self).get_initial()
        initial['owner'] = self.request.user
        return initial


class IndexView(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView):
    template_name = "network/index.html"

    def get_context_data(self, **kwargs):
        context = super(IndexView, self).get_context_data(**kwargs)

        size = 13
        blacklists = BlacklistItem.objects.all().order_by(
            '-modified_at')[:size]
        domains = Domain.objects.all().order_by('-modified_at')[:size]
        groups = Group.objects.all().order_by('-modified_at')[:size]
        hosts = Host.objects.all().order_by('-modified_at')[:size]
        records = Record.objects.all().order_by('-modified_at')[:size]
        vlans = Vlan.objects.all().order_by('-modified_at')[:size]
        vlangroups = VlanGroup.objects.all().order_by('-modified_at')[:size]
        rules = Rule.objects.all().order_by('-modified_at')[:size]

        result_list = []
        for i in (sorted(chain(domains, groups, hosts, records, vlans,
                               vlangroups, rules),
                         key=lambda x: x.modified_at, reverse=True)[:size]):
            result_list.append(
                {
                    'class_name': unicode(i.__class__.__name__),
                    'modified_at': i.modified_at,
                    'created_at': i.created_at,
                    'name': unicode(i),
                    'link': i.get_absolute_url()
                })

        context['latest_blacklists'] = blacklists
        context['latest'] = result_list
        return context


class BlacklistList(LoginRequiredMixin, SuperuserRequiredMixin,
                    SingleTableView):
    model = BlacklistItem
    table_class = BlacklistItemTable
    template_name = "network/blacklist-list.html"
    table_pagination = False


class BlacklistDetail(LoginRequiredMixin, SuperuserRequiredMixin,
                      SuccessMessageMixin, UpdateView):
    model = BlacklistItem
    template_name = "network/blacklist-edit.html"
    form_class = BlacklistItemForm
    success_message = _(u'Successfully modified blacklist item %(ipv4)s.')

    def get_success_url(self):
        if 'pk' in self.kwargs:
            return reverse_lazy('network.blacklist', kwargs=self.kwargs)

    def get_context_data(self, **kwargs):
        context = super(BlacklistDetail, self).get_context_data(**kwargs)
        context['blacklist_pk'] = self.object.pk
        return context


class BlacklistCreate(LoginRequiredMixin, SuperuserRequiredMixin,
                      SuccessMessageMixin, CreateView):
    model = BlacklistItem
    template_name = "network/blacklist-create.html"
    form_class = BlacklistItemForm
    success_message = _(u'Successfully created blacklist item %(ipv4)s')


class BlacklistDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
    model = BlacklistItem
    template_name = "network/confirm/base_delete.html"

    def get_context_data(self, **kwargs):
        """ display more information about the object """
        context = super(BlacklistDelete, self).get_context_data(**kwargs)
        if 'pk' in self.kwargs:
            to_delete = BlacklistItem.objects.get(pk=self.kwargs['pk'])
            context['object'] = "%s - %s" % (to_delete.ipv4, to_delete.reason)
            return context

    def get_success_url(self):
        next = self.request.POST.get('next')
        if next:
            return self.request.POST['next']
        else:
            return reverse_lazy('network.blacklist_list')


class DomainList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView):
    model = Domain
    table_class = DomainTable
    template_name = "network/domain-list.html"
    table_pagination = False


class DomainDetail(LoginRequiredMixin, SuperuserRequiredMixin,
                   SuccessMessageMixin, UpdateView):
    model = Domain
    template_name = "network/domain-edit.html"
    form_class = DomainForm
    success_message = _(u'Successfully modified domain %(name)s.')

    def get_success_url(self):
        if 'pk' in self.kwargs:
            return reverse_lazy('network.domain', kwargs=self.kwargs)

    def get_context_data(self, *args, **kwargs):
        context = super(DomainDetail, self).get_context_data(**kwargs)
        self.object = self.get_object()
        context['domain_pk'] = self.object.pk

        q = Record.objects.filter(
            domain=self.object,
            host__in=Host.objects.filter(
                interface__in=Interface.objects.filter(
                    instance__destroyed_at=None)
            )
        )
        context['record_list'] = SmallRecordTable(q)
        return context


class DomainCreate(LoginRequiredMixin, SuperuserRequiredMixin,
                   SuccessMessageMixin, InitialOwnerMixin, CreateView):
    model = Domain
    template_name = "network/domain-create.html"
    form_class = DomainForm
    success_message = _(u'Successfully created domain %(name)s.')


class DomainDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
    model = Domain
    template_name = "network/confirm/base_delete.html"

    def get_success_url(self):
        next = self.request.POST.get('next')
        if next:
            return self.request.POST['next']
        else:
            return reverse_lazy('network.domain_list')

    def delete(self, request, *args, **kwargs):
        self.object = self.get_object()
        if unicode(self.object) != request.POST.get('confirm'):
            messages.error(request, _(u"Object name does not match."))
            return self.get(request, *args, **kwargs)

        response = super(DomainDelete, self).delete(request, *args, **kwargs)
        messages.success(request, _(u"Domain successfully deleted."))
        return response

    def get_context_data(self, **kwargs):
        context = super(DomainDelete, self).get_context_data(**kwargs)

        records_from_hosts = _(u'Records from hosts')
        deps = []
        # vlans
        vlans = Vlan.objects.filter(domain=self.object).all()
        if len(vlans) > 0:
            deps.append({
                'name': _('Vlans'),
                'data': vlans
            })

            # hosts
            hosts = Host.objects.filter(vlan__in=deps[0]['data'])
            if len(hosts) > 0:
                deps.append({
                    'name': _('Hosts'),
                    'data':  hosts
                })

                # records
                records = Record.objects.filter(
                    host__in=deps[1]['data']
                    # Q(domain=self.object) | (host__in=deps[1]['data'])
                )
                if len(records) > 0:
                    deps.append({
                        'name': records_from_hosts,
                        'data': records
                    })

        records = Record.objects.filter(domain=self.object)
        if len(records) > 0:
            # to filter out doubles (records from hosts and domains)
            indexes = map(itemgetter('name'), deps)
            n = indexes.index(records_from_hosts) if len(indexes) > 0 else 0
            deps.append({
                'name': u'Records only from the domain',
                'data': records.exclude(pk__in=deps[n]['data']) if n > 0
                else records
            })

        context['deps'] = deps
        context['confirmation'] = True
        return context


class FirewallList(LoginRequiredMixin, SuperuserRequiredMixin,
                   SingleTableView):
    model = Firewall
    table_class = FirewallTable
    template_name = "network/firewall-list.html"
    table_pagination = False


class FirewallDetail(LoginRequiredMixin, SuperuserRequiredMixin,
                     SuccessMessageMixin, UpdateView):
    model = Firewall
    template_name = "network/firewall-edit.html"
    form_class = FirewallForm
    success_message = _(u'Succesfully modified firewall.')

    def get_success_url(self):
        if 'pk' in self.kwargs:
            return reverse_lazy('network.firewall', kwargs=self.kwargs)

    def get_context_data(self, **kwargs):
        context = super(FirewallDetail, self).get_context_data(**kwargs)
        rules = Rule.objects.filter(firewall=self.object)
        context['rule_table'] = FirewallRuleTable(rules,
                                                  request=self.request)
        return context


class FirewallCreate(LoginRequiredMixin, SuperuserRequiredMixin,
                     SuccessMessageMixin, CreateView):
    model = Firewall
    template_name = "network/firewall-create.html"
    form_class = FirewallForm
    success_message = _(u'Successfully created firewall.')


class FirewallDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
    model = Firewall
    template_name = "network/confirm/base_delete.html"

    def get_success_url(self):
        next = self.request.POST.get('next')
        if next:
            return next
        else:
            return reverse_lazy('network.firewall_list')


class GroupList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView):
    model = Group
    table_class = GroupTable
    template_name = "network/group-list.html"
    table_pagination = False


class GroupCreate(LoginRequiredMixin, SuperuserRequiredMixin,
                  SuccessMessageMixin, InitialOwnerMixin, CreateView):
    model = Group
    template_name = "network/group-create.html"
    form_class = GroupForm
    success_message = _(u'Successfully created host group %(name)s.')


class GroupDetail(LoginRequiredMixin, SuperuserRequiredMixin,
                  SuccessMessageMixin, UpdateView):
    model = Group
    template_name = "network/group-edit.html"
    form_class = GroupForm
    success_message = _(u'Successfully modified host group %(name)s.')

    def get_success_url(self):
        if 'pk' in self.kwargs:
            return reverse_lazy('network.group', kwargs=self.kwargs)

    def get_context_data(self, *args, **kwargs):
        context = super(GroupDetail, self).get_context_data(**kwargs)

        context['group_pk'] = self.object.pk

        # records
        q = Rule.objects.filter(hostgroup=self.object)
        context['rule_list'] = SmallRuleTable(q)
        return context


class GroupDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
    model = Group
    template_name = "network/confirm/base_delete.html"

    def get_success_url(self):
        next = self.request.POST.get('next')
        if next:
            return self.request.POST['next']
        else:
            return reverse_lazy('network.group_list')

    def get_context_data(self, *args, **kwargs):
        context = super(GroupDelete, self).get_context_data(**kwargs)
        context['group_pk'] = self.object.pk
        return context


class HostMagicMixin(MagicMixin):
    def _get_ajax(self, *args, **kwargs):
        GET = self.request.GET
        result = {}
        vlan = get_object_or_404(Vlan.objects, pk=GET.get("vlan", ""))
        if "ipv4" in GET:
            try:
                result["ipv6"] = vlan.convert_ipv4_to_ipv6(GET["ipv4"]) or ""
            except:
                result["ipv6"] = ""
        else:
            try:
                result.update(vlan.get_new_address())
            except ValidationError:
                result["ipv4"] = ""
                result["ipv6"] = ""
        return result


class HostList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView):
    model = Host
    table_class = HostTable
    template_name = "network/host-list.html"
    table_pagination = False

    def get_context_data(self, **kwargs):
        context = super(HostList, self).get_context_data(**kwargs)
        q = Vlan.objects.all().order_by("name")
        context['vlans'] = q
        return context

    def get_table_data(self):
        vlan_id = self.request.GET.get('vlan')
        if vlan_id:
            data = Host.objects.filter(vlan=vlan_id).select_related()
        else:
            data = Host.objects.select_related()

        search = self.request.GET.get("s")
        if search:
            data = data.filter(Q(hostname__icontains=search) |
                               Q(ipv4=search))  # ipv4 does not work TODO
        return data


class HostDetail(HostMagicMixin, LoginRequiredMixin, SuperuserRequiredMixin,
                 SuccessMessageMixin, UpdateView):
    model = Host
    template_name = "network/host-edit.html"
    form_class = HostForm
    success_message = _(u'Successfully modified host %(hostname)s.')

    def _get_ajax(self, *args, **kwargs):
        if "vlan" not in self.request.GET:
            host = Host.objects.get(pk=kwargs['pk'])
            host = {
                'hostname': host.hostname,
                'ipv4': str(host.ipv4),
                'ipv6': str(host.ipv6),
                'fqdn': host.get_fqdn()
            }
            return host
        else:
            return super(HostDetail, self)._get_ajax(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        return super(HostDetail, self).get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        pk = self.kwargs.get('pk')
        # this is usually not None (well, with curl and whatnot it can be)
        if pk:
            groups = Host.objects.get(pk=pk).groups.all()
            groups = [i.pk for i in groups]
            # request.POST is immutable
            post_copy = request.POST.copy()
            post_copy.setlist('groups', groups)
            request.POST = post_copy
            return super(HostDetail, self).post(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(HostDetail, self).get_context_data(**kwargs)
        # own rules
        q = Rule.objects.filter(host=self.object).all()
        context['rule_list'] = SmallRuleTable(q)

        # rules from host groups
        group_rule_list = []
        for group in self.object.groups.all():
            q = Rule.objects.filter(hostgroup=group).all()
            group_rule_list.append({
                'table': SmallGroupRuleTable(q),
                'name': unicode(group),
                'pk': group.pk
            })
        context['group_rule_list'] = group_rule_list

        # available groups
        rest = Group.objects.exclude(pk__in=self.object.groups.all()).all()
        context['not_used_groups'] = rest

        # set host pk (we need this for URL-s)
        context['host_pk'] = self.kwargs['pk']

        from network.tables import HostRecordsTable
        context['records_table'] = HostRecordsTable(
            Record.objects.filter(host=self.get_object()),
            request=self.request, template="django_tables2/table_no_page.html"
        )

        return context

    def get_success_url(self):
        if 'pk' in self.kwargs:
            return reverse_lazy('network.host', kwargs=self.kwargs)


class HostCreate(HostMagicMixin, LoginRequiredMixin, SuperuserRequiredMixin,
                 SuccessMessageMixin, InitialOwnerMixin, CreateView):
    model = Host
    template_name = "network/host-create.html"
    form_class = HostForm
    success_message = _(u'Successfully created host %(hostname)s.')

    def get_initial(self):
        initial = super(HostCreate, self).get_initial()

        for i in ("vlan", "mac", "hostname"):
            if i in self.request.GET and i not in self.request.POST:
                initial[i] = self.request.GET[i]
        if "vlan" in initial:
            if not initial['vlan'].isnumeric():
                raise Http404()
            vlan = get_object_or_404(Vlan.objects, pk=initial['vlan'])
            try:
                initial.update(vlan.get_new_address())
            except ValidationError as e:
                messages.error(self.request, e.message)
        return initial


class HostDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
    model = Host
    template_name = "network/confirm/base_delete.html"

    def get_success_url(self):
        next = self.request.POST.get('next')
        if next:
            return self.request.POST['next']
        else:
            return reverse_lazy('network.host_list')

    def get_context_data(self, *args, **kwargs):
        context = super(HostDelete, self).get_context_data(**kwargs)

        deps = []
        records = Record.objects.filter(host=self.object).all()
        if records:
            deps.append({
                'name': _('Records'),
                'data': records
            })

        context['deps'] = deps
        context['confirmation'] = True
        return context

    def delete(self, request, *args, **kwargs):
        self.object = self.get_object()
        if unicode(self.object) != request.POST.get('confirm'):
            messages.error(request, _(u"Object name does not match."))
            return self.get(request, *args, **kwargs)

        response = super(HostDelete, self).delete(request, *args, **kwargs)
        messages.success(request, _(u"Host successfully deleted."))
        return response


class RecordList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView):
    model = Record
    table_class = RecordTable
    template_name = "network/record-list.html"
    table_pagination = False

    def get_context_data(self, **kwargs):
        context = super(RecordList, self).get_context_data(**kwargs)
        context['types'] = Record.CHOICES_type
        return context

    def get_table_data(self):
        type_id = self.request.GET.get('type')
        if type_id:
            data = Record.objects.filter(type=type_id).select_related()
        else:
            data = Record.objects.select_related()
        return data


class RecordDetail(LoginRequiredMixin, SuperuserRequiredMixin,
                   SuccessMessageMixin, UpdateView):
    model = Record
    template_name = "network/record-edit.html"
    form_class = RecordForm
    # TODO fqdn
    success_message = _(u'Successfully modified record.')

    def get_context_data(self, **kwargs):
        context = super(RecordDetail, self).get_context_data(**kwargs)
        context['fqdn'] = self.object.fqdn
        context['record_pk'] = self.object.pk
        return context

    def get_success_url(self):
        if 'pk' in self.kwargs:
            return reverse_lazy('network.record', kwargs=self.kwargs)


class RecordCreate(LoginRequiredMixin, SuperuserRequiredMixin,
                   SuccessMessageMixin, InitialOwnerMixin, CreateView):
    model = Record
    template_name = "network/record-create.html"
    form_class = RecordForm
    # TODO fqdn
    success_message = _(u'Successfully created record.')

    def get_initial(self):
        initial = super(RecordCreate, self).get_initial()
        initial['domain'] = self.request.GET.get('domain')

        host_pk = self.request.GET.get("host")
        try:
            host = Host.objects.get(pk=host_pk)
        except (Host.DoesNotExist, ValueError):
            host = None

        if host:
            initial.update({
                'type': "CNAME",
                'host': host,
                'address': host.get_fqdn(),
            })

        return initial


class RecordDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
    model = Record
    template_name = "network/confirm/base_delete.html"

    def get_success_url(self):
        next = self.request.POST.get('next')
        if next:
            return self.request.POST['next']
        else:
            return reverse_lazy('network.record_list')


class RuleList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView):
    model = Rule
    table_class = RuleTable
    template_name = "network/rule-list.html"
    table_pagination = False

    def get_context_data(self, **kwargs):
        self.types = OrderedDict([
            ('vlan', _("Vlan")), ('vlangroup', _("Vlan group")),
            ('host', _("Host")), ('hostgroup', _("Host group")),
            ('firewall', _("Firewall"))
        ])
        context = super(RuleList, self).get_context_data(**kwargs)
        context['types'] = self.types
        return context

    def get_table_data(self):
        rules = Rule.objects.select_related('host', 'hostgroup', 'vlan',
                                            'vlangroup', 'firewall',
                                            'foreign_network', 'owner')

        rule_type = self.request.GET.get("type")
        if rule_type and rule_type in self.types.keys():
            rules = rules.filter(**{'%s__isnull' % rule_type: False})
        return rules


class RuleDetail(LoginRequiredMixin, SuperuserRequiredMixin,
                 SuccessMessageMixin, UpdateView):
    model = Rule
    template_name = "network/rule-edit.html"
    form_class = RuleForm
    success_message = _(u'Successfully modified rule.')

    def get_success_url(self):
        if 'pk' in self.kwargs:
            return reverse_lazy('network.rule', kwargs=self.kwargs)

    def get_context_data(self, **kwargs):
        context = super(RuleDetail, self).get_context_data(**kwargs)

        rule = self.get_object()

        context['rule'] = rule
        return context


class RuleCreate(LoginRequiredMixin, SuperuserRequiredMixin,
                 SuccessMessageMixin, InitialOwnerMixin, CreateView):
    model = Rule
    template_name = "network/rule-create.html"
    form_class = RuleForm
    success_message = _(u'Successfully created rule.')

    def get_initial(self):
        initial = super(RuleCreate, self).get_initial()
        initial.update({
            'host': self.request.GET.get('host'),
            'hostgroup': self.request.GET.get('hostgroup')
        })
        return initial


class RuleDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
    model = Rule
    template_name = "network/confirm/base_delete.html"

    def get_success_url(self):
        next = self.request.POST.get('next')
        if next:
            return next
        else:
            return reverse_lazy('network.rule_list')


class SwitchPortList(LoginRequiredMixin, SuperuserRequiredMixin,
                     SingleTableView):
    model = SwitchPort
    table_class = SwitchPortTable
    template_name = "network/switch-port-list.html"
    table_pagination = False


class SwitchPortDetail(LoginRequiredMixin, SuperuserRequiredMixin,
                       SuccessMessageMixin, UpdateView):
    model = SwitchPort
    template_name = "network/switch-port-edit.html"
    form_class = SwitchPortForm
    success_message = _(u'Succesfully modified switch port.')

    def get_success_url(self):
        if 'pk' in self.kwargs:
            return reverse_lazy('network.switch_port', kwargs=self.kwargs)

    def get_context_data(self, **kwargs):
        context = super(SwitchPortDetail, self).get_context_data(**kwargs)
        context['switch_port_pk'] = self.object.pk
        context['devices'] = EthernetDevice.objects.filter(
            switch_port=self.object.pk)
        return context


class SwitchPortCreate(LoginRequiredMixin, SuperuserRequiredMixin,
                       SuccessMessageMixin, CreateView):
    model = SwitchPort
    template_name = "network/switch-port-create.html"
    form_class = SwitchPortForm
    success_message = _(u'Successfully created switch port.')


class SwitchPortDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
    model = SwitchPort
    template_name = "network/confirm/base_delete.html"

    def get_success_url(self):
        next = self.request.POST.get('next')
        if next:
            return next
        else:
            return reverse_lazy('network.switch_port_list')


class VlanList(LoginRequiredMixin, SuperuserRequiredMixin, SingleTableView):
    model = Vlan
    table_class = VlanTable
    template_name = "network/vlan-list.html"
    table_pagination = False


class VlanAclUpdateView(AclUpdateView):
    model = Vlan


class VlanMagicMixin(MagicMixin):
    def _get_ajax(self, *args, **kwargs):
        GET = self.request.GET
        result = {}
        if "network4" in GET and "network6" in GET:
            try:
                result["ipv6_template"], result["host_ipv6_prefixlen"] = (
                    Vlan._magic_ipv6_template(IPNetwork(GET['network4']),
                                              IPNetwork(GET['network6'])))
            except:
                result["ipv6_template"] = result["host_ipv6_prefixlen"] = ""
        return result


class VlanDetail(VlanMagicMixin, LoginRequiredMixin, SuperuserRequiredMixin,
                 SuccessMessageMixin, UpdateView):
    model = Vlan
    template_name = "network/vlan-edit.html"
    form_class = VlanForm
    slug_field = 'vid'
    slug_url_kwarg = 'vid'
    success_message = _(u'Succesfully modified vlan %(name)s.')

    def get_context_data(self, **kwargs):
        context = super(VlanDetail, self).get_context_data(**kwargs)
        context['host_list'] = SmallHostTable(self.object.host_set.all())
        context['dhcp_list'] = SmallDhcpTable(self.object.get_dhcp_clients())
        context['vlan_vid'] = self.kwargs.get('vid')
        context['acl'] = AclUpdateView.get_acl_data(
            self.object, self.request.user, 'network.vlan-acl')
        context['aclform'] = AclUserOrGroupAddForm()
        return context

    success_url = reverse_lazy('network.vlan_list')


class VlanCreate(VlanMagicMixin, LoginRequiredMixin, SuperuserRequiredMixin,
                 SuccessMessageMixin, InitialOwnerMixin, CreateView):
    model = Vlan
    template_name = "network/vlan-create.html"
    form_class = VlanForm
    success_message = _(u'Successfully created vlan %(name)s.')


class VlanDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
    model = Vlan
    template_name = "network/confirm/base_delete.html"

    def get_success_url(self):
        next = self.request.POST.get('next')
        if next:
            return next
        else:
            return reverse_lazy('network.vlan_list')

    def get_object(self, queryset=None):
        """ we identify vlans by vid and not pk """
        return Vlan.objects.get(vid=self.kwargs['vid'])

    def delete(self, request, *args, **kwargs):
        self.object = self.get_object()
        if unicode(self.object) != request.POST.get('confirm'):
            messages.error(request, _(u"Object name does not match."))
            return self.get(request, *args, **kwargs)

        response = super(VlanDelete, self).delete(request, *args, **kwargs)
        messages.success(request, _(u"Vlan successfully deleted."))
        return response

    def get_context_data(self, **kwargs):
        context = super(VlanDelete, self).get_context_data(**kwargs)

        deps = []
        # hosts
        hosts = Host.objects.filter(vlan=self.object).all()
        if len(hosts) > 0:
            deps.append({
                'name': _('Hosts'),
                'data': hosts
            })

            # records
            records = Record.objects.filter(host__in=deps[0]['data'])
            if len(records) > 0:
                deps.append({
                    'name': _('Records'),
                    'data':  records
                })

        context['deps'] = deps
        context['confirmation'] = True
        return context


class VlanGroupList(LoginRequiredMixin, SuperuserRequiredMixin,
                    SingleTableView):
    model = VlanGroup
    table_class = VlanGroupTable
    template_name = "network/vlan-group-list.html"
    table_pagination = False


class VlanGroupDetail(LoginRequiredMixin, SuperuserRequiredMixin,
                      SuccessMessageMixin, UpdateView):
    model = VlanGroup
    template_name = "network/vlan-group-edit.html"
    form_class = VlanGroupForm
    success_url = reverse_lazy('network.vlan_group_list')
    success_message = _(u'Successfully modified vlan group %(name)s.')

    def get_context_data(self, *args, **kwargs):
        context = super(VlanGroupDetail, self).get_context_data(**kwargs)
        context['vlangroup_pk'] = self.object.pk
        return context


class VlanGroupCreate(LoginRequiredMixin, SuperuserRequiredMixin,
                      SuccessMessageMixin, InitialOwnerMixin, CreateView):
    model = VlanGroup
    template_name = "network/vlan-group-create.html"
    form_class = VlanGroupForm
    success_message = _(u'Successfully created vlan group %(name)s.')


class VlanGroupDelete(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
    model = VlanGroup
    template_name = "network/confirm/base_delete.html"

    def get_success_url(self):
        next = self.request.POST.get('next')
        if next:
            return next
        else:
            return reverse_lazy('network.vlan_group_list')


def remove_host_group(request, **kwargs):
    host = Host.objects.get(pk=kwargs['pk'])
    group = Group.objects.get(pk=kwargs['group_pk'])

    # for get we show the confirmation page
    if request.method == "GET":
        return render(request,
                      'network/confirm/remove_host_group.html',
                      {
                          'group': group.name,
                          'host': host.hostname
                      })

    # for post we actually remove the group from the host
    elif request.method == "POST":
        host.groups.remove(group)
        if not request.is_ajax():
            messages.success(request, _(u"Successfully removed %(host)s from "
                                        "%(group)s group." % {
                                            'host': host,
                                            'group': group
                                        }))
        return redirect(reverse_lazy('network.host',
                                     kwargs={'pk': kwargs['pk']}))


def add_host_group(request, **kwargs):
    group_pk = request.POST.get('group')
    if request.method == "POST" and group_pk:
        host = Host.objects.get(pk=kwargs['pk'])
        group = Group.objects.get(pk=group_pk)
        host.groups.add(group)
        if not request.is_ajax():
            messages.success(request, _(u"Successfully added %(host)s to group"
                                        " %(group)s." % {
                                            'host': host,
                                            'group': group
                                        }))
        return redirect(reverse_lazy('network.host', kwargs=kwargs))


def remove_switch_port_device(request, **kwargs):
    device = EthernetDevice.objects.get(pk=kwargs['device_pk'])
    # for get we show the confirmation page
    if request.method == "GET":
        return render(request, 'network/confirm/base_delete.html',
                      {'object': device})

    # for post we actually remove the group from the host
    elif request.method == "POST":
        device.delete()
        if not request.is_ajax():
            messages.success(request, _(u"Successfully deleted ethernet device"
                                        " %(name)s." % {
                                            'name': device.name,
                                        }))
        return redirect(reverse_lazy('network.switch_port',
                                     kwargs={'pk': kwargs['pk']}))


def add_switch_port_device(request, **kwargs):
    device_name = request.POST.get('device_name')

    if (request.method == "POST" and device_name and len(device_name) > 0 and
            EthernetDevice.objects.filter(name=device_name).count() == 0):

        switch_port = SwitchPort.objects.get(pk=kwargs['pk'])
        new_device = EthernetDevice(name=device_name, switch_port=switch_port)
        new_device.save()
        if not request.is_ajax():
            messages.success(request, _(u"Successfully added %(name)s to this"
                                        " switch port" % {
                                            'name': device_name,
                                        }))
        return redirect(reverse_lazy('network.switch_port', kwargs=kwargs))

    elif not len(device_name) > 0:
        messages.error(request, _("Ethernet device name cannot be empty."))
        return redirect(reverse_lazy('network.switch_port', kwargs=kwargs))
    elif EthernetDevice.objects.get(name=device_name) is not None:
        messages.error(request, _("There is already an ethernet device with"
                                  " that name."))
        return redirect(reverse_lazy('network.switch_port', kwargs=kwargs))
