from typing_extensions import Required
from rest_framework.renderers import JSONRenderer
from rest_framework import serializers
from django.contrib.auth.models import Group, User

from vm.models import Instance, InstanceTemplate, Lease, Interface, Node, InstanceActivity
from firewall.models import Vlan, Rule
from storage.models import Disk, StorageActivity
from vm.models.common import Variable
from exam.models import Exam

class RuleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Rule
        fields = '__all__'

class InstanceActivitySerializer(serializers.ModelSerializer):
    get_percentage = serializers.IntegerField()
    result_data = serializers.JSONField()

    class Meta:
        model = InstanceActivity
        fields = ('id', 'instance', 'resultant_state', 'interruptible', 'activity_code', 'parent', 
                    'task_uuid', 'user', 'started', 'finished', 'succeeded', 'result_data', 'created', 'modified', 'get_percentage')

class StorageActivitySerializer(serializers.ModelSerializer):

    class Meta:
        model = StorageActivity
        fields = ('id', 'parent', 'task_uuid', 'user', 'started', 'finished', 'succeeded', 'result_data', 'created', 'modified', 'disk')

    

class GroupSerializer(serializers.ModelSerializer): 
    class Meta:
        model = Group
        fields = ('id', 'name', 'user_set')


class ExamSerializer(serializers.ModelSerializer):
    class Meta:
        model = Exam
        fields = ('id', 'name', 'owner', 'description', 'template')


class UserSerializer(serializers.ModelSerializer):    
    class Meta:
        model = User
        fields = ('id', 'username', 'email', 'is_staff', 'groups', 'is_superuser', 'first_name', 'last_name')


class NodeSerializer(serializers.ModelSerializer):
    class Meta:
        model = Node
        fields = [ 'id', 'name', 'priority', 'host', 'enabled', 'schedule_enabled',
                    'traits', 'overcommit', 'ram_weight', 'cpu_weight', 'time_stamp' ]


class InstanceTemplateSerializer(serializers.ModelSerializer):
    class Meta:
        model = InstanceTemplate
        fields = [ 'id', 'name', 'description', 'parent', 'owner', 'access_method', 'boot_menu', 
                    'lease', 'raw_data', 'cloud_init', 'ci_network_config', 'ci_meta_data', 'ci_user_data', 'system',
                    'has_agent', 'num_cores', 'ram_size', 'max_ram_size', 'arch', 'priority', 'disks', 'num_cores_max']


class LeaseSerializer(serializers.ModelSerializer):
    class Meta:
        model = Lease
        fields = [ 'id', 'name', 'suspend_interval_seconds', 'delete_interval_seconds']


class VariableSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Variable
        fields = [ 'id', 'key', 'value', 'url']


class DiskSerializer(serializers.ModelSerializer):
    class Meta:
        model = Disk
        fields = ['id', 'name', 'filename', 'datastore', 'type', 'bus', 'size', 'base',
                    'dev_num', 'destroyed', 'ci_disk', 'is_ready']


class InstanceSerializer(serializers.ModelSerializer):
    ipv4addr = serializers.SerializerMethodField('get_ipv4')
    ipv6addr = serializers.SerializerMethodField('get_ipv6')
    vlans = serializers.SerializerMethodField('get_vlans')
    macaddr = serializers.SerializerMethodField('get_mac')
    sshportipv4 = serializers.SerializerMethodField('get_sshportipv4')
    hostipv4 = serializers.SerializerMethodField('get_hostipv4')
    disks = serializers.SerializerMethodField('get_disks')
    #interfaces = serializers.SerializerMethodField('get_interfaces')

    def get_disks(self, i):
        return list(disk.id for disk in i.disks.filter(ci_disk=False).all())

    def get_ipv4(self, i):
        return str(i.ipv4)

    def get_ipv6(self, i):
        return str(i.ipv6)

    def get_mac(self, i):
        return str(i.mac).lower()

    def get_vlans(self, i):
        return list(net.vlan.id for net in i.interface_set.all() if net.host)

    def get_interfaces(self, i):
        return i.interface_set.all()

    def get_sshportipv4(self, i):
        return i.get_connect_port(use_ipv6=False)

    def get_hostipv4(self, i):
        return i.get_connect_host(use_ipv6=False)

    class Meta:
        model = Instance
        fields = ['id', 'name', 'description', 'status', 'owner', 'access_method', 'boot_menu', 'pw', 'is_base', 'macaddr',
                    'lease', 'raw_data', 'cloud_init', 'ci_meta_data', 'ci_user_data', 'ci_network_config', 'system', 'req_traits', 'interface_set',
                    'has_agent', 'num_cores', 'num_cores_max', 'ram_size', 'max_ram_size', 'arch', 'priority', 'disks', 'node', 'ipv4addr', 'ipv6addr', 'vlans',
                    'hookurl', 'sshportipv4', 'hostipv4']
        extra_kwargs = {
            'disks': {'required': False, 'allow_empty': True,},
            'req_traits': {'required': False, 'allow_empty': True,},
            'interface_set': {'required': False, 'allow_empty': True,},
            'hookurl': {'required': False },
            'ci_network_config': {'required': False, },
            'ci_user_data': {'required': False, },
            'ci_meta_data': {'required': False, },
            'raw_data': {'required': False, },
            'sshportipv4': {'required': False, },
            'hostipv4': {'required': False, },
            'num_cores_max': {'required': False, },
        }


class InterfaceSerializer(serializers.ModelSerializer):
    mac = serializers.SerializerMethodField('get_mac')
    ipv4 = serializers.SerializerMethodField('get_ipv4')
    ipv6 = serializers.SerializerMethodField('get_ipv6')

    def get_mac(self, i):
        return str(i.mac)

    def get_ipv4(self, i):
        return str(i.ipv4)

    def get_ipv6(self, i):
        return str(i.ipv6)

    class Meta:
        model = Interface
        fields = ['id', 'vlan', 'host', 'instance', 'model', 'host', 'mac', 'ipv4', 'ipv6']


class VlanSerializer(serializers.ModelSerializer):
    class Meta:
        model = Vlan
        fields = ['id', 'vid', 'name', 'description', 'comment', 'domain']


class CreateDiskSerializer(serializers.Serializer):
    size = serializers.CharField(max_length=50)
    name = serializers.CharField(max_length=100)
    datastore = serializers.CharField(max_length=40, required=False, allow_blank=True, default=None)


class ResizeDiskSerializer(serializers.Serializer):
    size = serializers.CharField(max_length=50)
    disk = serializers.IntegerField()

class DownloadDiskSerializer(serializers.Serializer):
    url = serializers.CharField(max_length=500)
    name = serializers.CharField(max_length=100)
    resize = serializers.CharField(max_length=30, required=False, allow_blank=True, default=None)
    datastore = serializers.CharField(max_length=40, required=False, allow_blank=True, default=None)

    class Meta:
        extra_kwargs = {'resize': {'required': False, 'allow_blank': True, 'allow_empty': True }}

class CreateTemplateSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=100)

class DestroyDiskSerializer(serializers.Serializer):
    disk = serializers.IntegerField()
    instance = serializers.IntegerField(required=False)

    class Meta:
        extra_kwargs = {'instance': {'required': False, 'allow_null': True}}

class AddPortSerializer(serializers.Serializer):
    type = serializers.CharField(max_length=5)
    port_destination = serializers.IntegerField()
    port_source = serializers.IntegerField(required=False)
    forwarding = serializers.BooleanField(required=False)

class VMDeploySerializer(serializers.Serializer):
    node = serializers.IntegerField(required=False)

    class Meta:
        extra_kwargs = {'node': {'required': False, 'allow_null': True}}