# models.py -  VNOD Local Service

from django.db import models
from core.models import Service
from core.models import PlCoreBase

VNODLOCAL_KIND = "vnodlocal"
SERVICE_NAME = 'vnodlocal'

class VnodLocalSystem(PlCoreBase):
    class Meta:
        app_label = VNODLOCAL_KIND
        verbose_name = "VNOD Local System"

    ADMINISTRATIVE_STATE = (
        ('enabled', 'Enabled'),
        ('disabled', 'Disabled')
    )

    name = models.CharField(unique=True,
                        verbose_name="Name",
                        max_length=256,
                        editable=True)

    description = models.CharField(verbose_name="Description",
                               max_length=1024,
                               editable=True)

    restUrl = models.CharField(verbose_name="MetroNetwork Rest URL",
                           max_length=256,
                           editable=True)

    username = models.CharField(verbose_name='Username',
                                max_length=32,
                                editable=True,
                                blank=True)

    password = models.CharField(max_length=32,
                                verbose_name='Password',
                                editable=True,
                                blank=True)

    administrativeState = models.CharField(choices=ADMINISTRATIVE_STATE,
                                       default='enabled',
                                       verbose_name="AdministrativeState",
                                       max_length=16,
                                       editable=True)

    pseudowireprovider = models.CharField(unique=False,
                            verbose_name="Pseudowire Provider",
                            default='none',
                            max_length=256,
                            editable=True)

    networkControllerUrl = models.CharField(verbose_name="Network Controller URL",
                                          blank=True,
                                          max_length=256,
                                          editable=True)

    def __init__(self, *args, **kwargs):
        super(VnodLocalSystem, self).__init__(*args, **kwargs)


    def getAdminstrativeState(self):
        return self.administrativeState


    def setAdminstrativeState(self, value):
        self.administrativeState = value


    def getRestUrl(self):
        return self.restUrl


class VnodLocalService(Service):

    class Meta:
        app_label = VNODLOCAL_KIND
        verbose_name = "Virtual Network On Demand Local Service"

    ADMINISTRATIVE_STATE = (
        ('disabled', 'Disabled'),
        ('configurationrequested', 'ConfigurationRequested'),
        ('configurationfailed', 'ConfigurationFailed'),
        ('configured', 'Configured'),
        ('activationrequested', 'ActivationRequested'),
        ('activationfailed', 'ActivationFailed'),
        ('enabled', 'Enabled'),
        ('deactivationrequested', 'DeactivationRequested')
    )

    OPERATIONALSTATE = (
        ('active', 'Active'),
        ('inactivereported', 'InactiveReported'),
        ('inactive', 'Inactive'),
        ('activereported', 'ActiveReported')
    )

    portid = models.CharField(verbose_name="PortId", blank=True, max_length=256, editable=True)
    vlanid = models.CharField(verbose_name="VlanId", blank=True, max_length=256, editable=True)
    servicehandle = models.CharField(verbose_name="Service Handle", max_length=256, editable=True)
    autoattached = models.BooleanField(verbose_name="Auto-Attached", default=False, editable=True)

    administrativeState = models.CharField(choices=ADMINISTRATIVE_STATE,
                                           default='disabled',
                                           verbose_name="AdministrativeState",
                                           max_length=64,
                                           editable=True)

    operstate = models.CharField(choices=OPERATIONALSTATE,
                                 default='inactive',
                                 verbose_name="OperationalState",
                                 max_length=64,
                                 editable=True)


    def __init__(self, *args, **kwargs):
        super(VnodLocalService, self).__init__(*args, **kwargs)

    def __unicode__(self):  return u'%s:%s' % (self.servicehandle, self.portid)


class VnodLocalPseudowireConnectorService(Service):

    class Meta:
        app_label = VNODLOCAL_KIND
        verbose_name = "Virtual Network On Demand Local Pseudo-wire Connector Service"

    ADMINISTRATIVE_STATE = (
        ('disabled', 'Disabled'),
        ('activationrequested', 'ActivationRequested'),
        ('enabled', 'Enabled'),
        ('deactivationrequested', 'DeactivationRequested')
    )

    OPERATIONALSTATE = (
        ('active', 'Active'),
        ('inactive', 'Inactive')
    )

    servicehandle = models.CharField(verbose_name="Service Handle", max_length=256, editable=True)
    pseudowirehandle = models.CharField(verbose_name="Pseudowirehandle", blank=True, max_length=256, editable=True)
    internalport = models.CharField(verbose_name="Internal Port", max_length=256, editable=True)

    vnodlocal = models.ForeignKey(VnodLocalService,
                                  related_name='VnodLocalService',
                                  verbose_name="VnodLocalService",
                                  null=True,
                                  editable=True,
                                  on_delete=models.CASCADE)

    administrativeState = models.CharField(choices=ADMINISTRATIVE_STATE,
                                           default='disabled',
                                           verbose_name="AdministrativeState",
                                           max_length=64,
                                           editable=True)

    operstate = models.CharField(choices=OPERATIONALSTATE,
                                 default='inactive',
                                 verbose_name="OperationalState",
                                 max_length=64,
                                 editable=True)


    def __init__(self, *args, **kwargs):
        super(VnodLocalPseudowireConnectorService, self).__init__(*args, **kwargs)
