
# Copyright 2017-present Open Networking Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


sync_attributes = ("wan_container_ip", "wan_container_mac", "wan_container_netbits",
                   "wan_container_gateway_ip", "wan_container_gateway_mac",
                   "wan_vm_ip", "wan_vm_mac")


def __init__(self, *args, **kwargs):
    super(VEGTenant, self).__init__(*args, **kwargs)
    self.cached_address_service_instance = None
@property
def address_service_instance(self):
    address_service_instance = self.get_newest_subscribed_tenant(AddressManagerServiceInstance)
    if not address_service_instance:
        return None

    # always return the same object when possible
    if (self.cached_address_service_instance) and (self.cached_address_service_instance.id == address_service_instance.id):
        return self.cached_address_service_instance

    address_service_instance.caller = self.creator
    self.cached_address_service_instance = address_service_instance
    return address_service_instance

@address_service_instance.setter
def address_service_instance(self, value):
    raise XOSConfigurationError("VEGTenant.address_service_instance setter is not implemented")

@property
def volt(self):
    from services.volt.models import VOLTTenant
    if not self.subscriber_tenant:
        return None
    volts = VOLTTenant.objects.filter(id=self.subscriber_tenant.id)
    if not volts:
        return None
    return volts[0]

@volt.setter
def volt(self, value):
    raise XOSConfigurationError("VEGTenant.volt setter is not implemented")

@property
def ssh_command(self):
    if self.instance:
        return self.instance.get_ssh_command()
    else:
        return "no-instance"

def get_address_service_instance_field(self, name, default=None):
    if self.address_service_instance:
        return getattr(self.address_service_instance, name, default)
    else:
        return default

@property
def wan_container_ip(self):
    return self.get_address_service_instance_field("public_ip", None)

@property
def wan_container_mac(self):
    return self.get_address_service_instance_field("public_mac", None)

@property
def wan_container_netbits(self):
    return self.get_address_service_instance_field("netbits", None)

@property
def wan_container_gateway_ip(self):
    return self.get_address_service_instance_field("gateway_ip", None)

@property
def wan_container_gateway_mac(self):
    return self.get_address_service_instance_field("gateway_mac", None)

@property
def wan_vm_ip(self):
    tags = Tag.objects.filter(content_type=self.instance.get_content_type_key(), object_id=self.instance.id, name="vm_vrouter_tenant")
    if tags:
        tenant = AddressManagerServiceInstance.objects.get(id=tags[0].value)
        return tenant.public_ip
    else:
        raise Exception("no vm_vrouter_tenant tag for instance %s" % o.instance)

@property
def wan_vm_mac(self):
    tags = Tag.objects.filter(content_type=self.instance.get_content_type_key(), object_id=self.instance.id, name="vm_vrouter_tenant")
    if tags:
        tenant = AddressManagerServiceInstance.objects.get(id=tags[0].value)
        return tenant.public_mac
    else:
        raise Exception("no vm_vrouter_tenant tag for instance %s" % o.instance)

@property
def is_synced(self):
    return (self.enacted is not None) and (self.enacted >= self.updated)

@is_synced.setter
def is_synced(self, value):
    pass
def save(self, *args, **kwargs):
    if not self.creator:
        if not getattr(self, "caller", None):
            # caller must be set when creating a vEG since it creates a slice
            raise XOSProgrammingError("VEGTenant's self.caller was not set")
        self.creator = self.caller
        if not self.creator:
            raise XOSProgrammingError("VEGTenant's self.creator was not set")

    super(VEGTenant, self).save(*args, **kwargs)


def delete(self, *args, **kwargs):
    super(VEGTenant, self).delete(*args, **kwargs)
