import os
import base64
from collections import defaultdict
from netaddr import IPAddress, IPNetwork
from django.db.models import F, Q
from planetstack.config import Config
from observer.openstacksyncstep import OpenStackSyncStep
from core.models.deployment import Deployment
from core.models.site import SiteDeployments
from core.models.slice import Slice, SliceDeployments
from core.models.user import UserDeployments
from util.logger import Logger, logging

logger = Logger(level=logging.INFO)

class SyncSliceDeployments(OpenStackSyncStep):
    provides=[SliceDeployments]
    requested_interval=0

    def fetch_pending(self):
        # slice deployments are not visible to users. We must ensure
        # slices are deployed at all deploymets available to their site.
        site_deployments = SiteDeployments.objects.all()
        site_deploy_lookup = defaultdict(list)
        for site_deployment in site_deployments:
            site_deploy_lookup[site_deployment.site].append(site_deployment.deployment)
        
        slice_deployments = SliceDeployments.objects.all()
        slice_deploy_lookup = defaultdict(list)
        for slice_deployment in slice_deployments:
            slice_deploy_lookup[slice_deployment.slice].append(slice_deployment.deployment)
        
        all_deployments = Deployment.objects.all() 
        for slice in Slice.objects.all():
            # slices are added to all deployments for now
            expected_deployments = all_deployments
            #expected_deployments = site_deploy_lookup[slice.site]
            for expected_deployment in expected_deployments:
                if slice not in slice_deploy_lookup or \
                   expected_deployment not in slice_deploy_lookup[slice]:
                    sd = SliceDeployments(slice=slice, deployment=expected_deployment)
                    sd.save()

        # now we can return all slice deployments that need to be enacted   
        return SliceDeployments.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))

    def get_next_subnet(self, deployment=None):
        # limit ourself to 10.0.x.x for now
        valid_subnet = lambda net: net.startswith('10.0')
        driver = self.driver.admin_driver(deployment=deployment)
        subnets = driver.shell.quantum.list_subnets()['subnets']
        ints = [int(IPNetwork(subnet['cidr']).ip) for subnet in subnets \
                if valid_subnet(subnet['cidr'])]
        ints.sort()
        if ints:
            last_ip = IPAddress(ints[-1])
        else:
            last_ip = IPAddress('10.0.0.1')
        last_ip = IPAddress(ints[-1])
        last_network = IPNetwork(str(last_ip) + "/24")
        next_network = IPNetwork(str(IPAddress(last_network) + last_network.size) + "/24")
        return next_network

    def sync_record(self, slice_deployment):
        logger.info("sync'ing slice deployment %s" % slice_deployment)
        if not slice_deployment.tenant_id:
            nova_fields = {'tenant_name': slice_deployment.slice.name,
                   'description': slice_deployment.slice.description,
                   'enabled': slice_deployment.slice.enabled}
            driver = self.driver.admin_driver(deployment=slice_deployment.deployment.name)
            tenant = driver.create_tenant(**nova_fields)
            slice_deployment.tenant_id = tenant.id

            # XXX give caller an admin role at the tenant they've created
            deployment_users = UserDeployments.objects.filter(user=slice_deployment.slice.creator,
                                                             deployment=slice_deployment.deployment)            
            if not deployment_users:
                logger.info("slice createor %s has not accout at deployment %s" % (slice_deployment.slice.creator, slice_deployment.deployment.name))
            else:
                deployment_user = deployment_users[0]
                # lookup user id at this deployment
                kuser= driver.shell.keystone.users.find(email=slice_deployment.slice.creator.email)

                # add required roles at the slice's tenant 
                driver.add_user_role(kuser.id, tenant.id, 'admin')
                    
                # refresh credentials using this tenant
                client_driver = self.driver.client_driver(caller=deployment_user.user,
                                                          tenant=tenant.name, 
                                                          deployment=slice_deployment.deployment.name)


        if slice_deployment.id and slice_deployment.tenant_id:
            driver = self.driver.admin_driver(deployment=slice_deployment.deployment.name)
            driver.update_tenant(slice_deployment.tenant_id,
                                 description=slice_deployment.slice.description,
                                 enabled=slice_deployment.slice.enabled)   

        slice_deployment.save()
