import os
import sys

from synchronizers.base.syncstep import SyncStep
from services.vnodlocal.models import *
import requests, json
from requests.auth import HTTPBasicAuth

from xos.logger import Logger, logging

# vnod local will be in steps/..
parentdir = os.path.join(os.path.dirname(__file__), "..")
sys.path.insert(0, parentdir)

logger = Logger(level=logging.INFO)


class SyncVnodLocalSystem(SyncStep):
    provides = [VnodLocalService]
    observes = VnodLocalService
    requested_interval = 0
    initialized = False

    def __init__(self, **args):
        SyncStep.__init__(self, **args)

    def fetch_pending(self, deletion=False):
        logger.info("VnodLocal fetch pending called")

        # Some comments to replace as we write the code

        #    The AdministrativeState state machine:
        #
        #               Diasabled (initial)
        #                    |
        #             ConfigurationRequested
        #             /      /            \
        #            /      /              \
        #      ConfigurationFailed      Configured---------DeactivationRequested
        #                                   \                      |
        #                         ActivationRequested              |
        #                         /      /        \                |
        #                        /      /          \               |
        #               ActivationFailed         Enabled -----------
        #
        #

        #  The  OperationalState state machine
        #
        #           active-----------------|
        #              |                   |
        #       inactivereported           |
        #              |                   |
        #          inactive----------activereported

        objs = []


        # The whole thing needs to be conditional on the VnodLocalSystem existing and being 'enabled'
        # This is the 'kill switch' in the system that is the first thing to check
        vnodlocalsystem = self.get_vnodlocal_system()

        if not vnodlocalsystem:
            logger.debug("No VnodLocal System Configured, skipping sync")
            return objs

        # Check to make sure the Metro Network System is enabled
        if vnodlocalsystem.administrativeState == 'disabled':
            # Nothing to do
            logger.debug("VnodLocal System configured - state is Disabled, skipping sync")
            return objs



        # Handle call when deletion is False
        if deletion is False:

            # First Part of Auto-attachement: What we need to do is ask the ECORD if there are any Spokes for our site
            # that are set to 'auto-attached' but are not currently actually attached
            # it will send back a list of servicehandles that meet that criteria. We will simply
            # check if we have already created a VnodLocal for that service handle, if we have do
            # nothing it should be still in progress. If we haven't create it, mark it as 'autoattached', set the
            # servicehandle and mark it as 'ConfigurationRequested'
            rest_url = vnodlocalsystem.restUrl
            sitename = vnodlocalsystem.name
            username = vnodlocalsystem.username
            password = vnodlocalsystem.password

            autoattachhandles = self.get_autoattachhandles(vnodlocalsystem)
            for autoattachhandle in autoattachhandles:
                # Check to see if it already exists - if not add it
                if not VnodLocalService.objects.filter(servicehandle=autoattachhandle).exists():
                    vnodlocal = VnodLocalService()
                    vnodlocal.servicehandle = autoattachhandle
                    vnodlocal.autoattached = True
                    vnodlocal.administrativeState = 'configurationrequested'
                    logger.debug("Adding Auto-attached VnodLocalService servicehandle: %s" % vnodlocal.servicehandle)
                    objs.append(vnodlocal)

            # Second Part of Auto-attachment
            # Look for auto-attachmed Services that are Configured, move them automaticaly to activationrequested
            autoattachconfigures = self.get_autoattachconfigured()
            for autoattachconfigure in autoattachconfigures:
                # Just bounce these forward to activationrequested to get them activated
                autoattachconfigure.administrativeState = 'activationrequested'
                objs.append(autoattachconfigure)


            # Check for admin status 'ConfigurationRequested'
            configreqs = VnodLocalService.objects.filter(administrativeState='configurationrequested')
            for configreq in configreqs:
                # Call the XOS Interface to configure the service
                logger.debug("Attempting to configure VnodLocalService servicehandle: %s" % configreq.servicehandle)
                # Add code to call REST api on the ECORD - For this state - we call VnodGlobal
                # with the servciehandle and sitename it
                # it gives us back the NNI port and Vlan Config
                # we then set our state to 'Configured' or 'ConfigurationFailed'
                servicehandle = configreq.servicehandle
                query = {"sitename": sitename, "servicehandle" : servicehandle}

                resp = requests.get("{}/vnodglobal_api_configuration/".format(rest_url), params=query,
                                    auth=HTTPBasicAuth(username, password))

                if resp.status_code == 200:
                    resp = resp.json()
                    # Success-path transitions to 'configured'
                    configreq.vlanid = resp['vlanid']
                    configreq.portid = resp['port']['name']
                    configreq.administrativeState = 'configured'

                    #update proxy adminstate in ecord
                    data = {"sitename": sitename, "servicehandle": servicehandle, "adminstate": 'configured',
                            "vlanid": configreq.vlanid, "portid": configreq.portid}
                    resp = requests.post("{}/vnodglobal_api_status/".format(rest_url), data=json.dumps(data),
                                     auth=HTTPBasicAuth(username, password))

                else:
                    configreq.administrativeState = 'configurationfailed'

                objs.append(configreq)


            # Check for admin status 'ActivationRequested'
            activationreqs = VnodLocalService.objects.filter(administrativeState='activationrequested')
            for acivationreq in activationreqs:
                # Call the XOS Interface to activate the service
                logger.debug("Attempting to activate VnodLocalService servicehandle: %s" % acivationreq.servicehandle)
                # Add code to call REST api on the ECORD - For this state we send the VnodGlobal
                # service our service handle, subscriber,
                # VnodLocalId (this id)
                # Once this is accepted we transition to the
                # Final state of 'Enabled' or 'ActivationFailed'
                servicehandle = acivationreq.servicehandle
                vnodlocalid = acivationreq.id
                vlanid = acivationreq.vlanid
                portid = acivationreq.portid

                data = {"sitename": sitename, "servicehandle": servicehandle, "vnodlocalid": vnodlocalid,
                        "vlanid": vlanid, "portid": portid, "activate": "true"}

                resp = requests.post("{}/vnodglobal_api_activation/".format(rest_url), data=json.dumps(data),
                                    auth=HTTPBasicAuth(username, password))

                if resp.status_code == 200:
                    # Success-path transitions to 'enabled'
                    acivationreq.administrativeState = 'enabled'

                    # update proxy adminstate in ecord
                    data = {"sitename": sitename, "servicehandle": servicehandle, "adminstate": 'enabled',
                            "vlanid": vlanid, "portid": portid, "operstate": "active"}
                    resp = requests.post("{}/vnodglobal_api_status/".format(rest_url), data=json.dumps(data),
                                         auth=HTTPBasicAuth(username, password))
                else:
                    acivationreq.administrativeState = 'activationfailed'

                    # update proxy adminstate in ecord
                    data = {"sitename": sitename, "servicehandle": servicehandle, "adminstate": 'impaired',
                            "operstate": "inactive", "vlanid": vlanid, "portid": portid}
                    resp = requests.post("{}/vnodglobal_api_status/".format(rest_url), data=json.dumps(data),
                                         auth=HTTPBasicAuth(username, password))

                objs.append(acivationreq)


            # Check for admin status 'DeactivationRequested'
            deactivationreqs = VnodLocalService.objects.filter(administrativeState='deactivationrequested')
            for deacivationreq in deactivationreqs:
                # Call the XOS Interface to de-actiavte the spoke
                logger.debug("Attempting to de-activate VnodLocalService servicehandle: %s" % deacivationreq.servicehandle)
                # Add code to call REST api on the ECORD - Report change to VnodGlobal
                servicehandle = deacivationreq.servicehandle
                vnodlocalid = deacivationreq.id
                vlanid = deacivationreq.vlanid
                portid = deacivationreq.portid


                data = {"sitename": sitename, "servicehandle": servicehandle, "vnodlocalid": vnodlocalid,
                        "vlanid": vlanid, "portid": portid, "activate": "false"}

                resp = requests.post("{}/vnodglobal_api_activation/".format(rest_url), data=json.dumps(data),
                                     auth=HTTPBasicAuth(username, password))

                if resp.status_code == 200:
                    # Success-path transitions to 'enabled'
                    deacivationreq.administrativeState = 'configured'
                else:
                    deacivationreq.administrativeState = 'deactivationfailed'

                # update proxy adminstate in ecord
                data = {"sitename": sitename, "servicehandle": servicehandle, "adminstate": 'impaired',
                        "vlanid": vlanid, "portid": portid}
                resp = requests.post("{}/vnodglobal_api_status/".format(rest_url), data=json.dumps(data),
                                     auth=HTTPBasicAuth(username, password))

                objs.append(deacivationreq)


            # Check for oper status inactive reported
            inactivereports = VnodLocalService.objects.filter(operstate='inactivereported')
            for inactivereport in inactivereports:
                # Call the XOS Interface to report operstate issue
                logger.debug("Attempting to report inactive VnodLocalService servicehandle: %s" % inactivereport.servicehandle)
                # Add code to call REST api on the ECORD - Report change to VnodGlobal

                servicehandle = inactivereport.servicehandle
                vlanid = inactivereport.vlanid
                portid = inactivereport.portid

                # update proxy operstate in ecord
                data = {"sitename": sitename, "servicehandle": servicehandle, "operstate": "inactive",
                        "adminstate":"impaired", "vlanid": vlanid, "portid": portid}
                resp = requests.post("{}/vnodglobal_api_status/".format(rest_url), data=json.dumps(data),
                                     auth=HTTPBasicAuth(username, password))

                # transition to 'inactive' state regardless of whether call to ECORD was successful?!?
                inactivereport.operstate = 'inactive'
                objs.append(inactivereport)


            # Check for oper status active reported
            activereports = VnodLocalService.objects.filter(operstate='activereported')
            for activereport in activereports:
                # Call the XOS Interface to report operstate issue
                logger.debug(
                    "Attempting to report active VnodLocalService servicehandle: %s" % activereport.servicehandle)

                servicehandle = activereport.servicehandle
                vlanid = activereport.vlanid
                portid = activereport.portid
                # Add code to call REST api on the ECORD - Report change to VnodGlobal.
                # update proxy operstate in ecord
                data = {"sitename": sitename, "servicehandle": servicehandle, "operstate": "active",
                        "vlanid": vlanid, "portid": portid}
                resp = requests.post("{}/vnodglobal_api_status/".format(rest_url), data=json.dumps(data),
                                 auth=HTTPBasicAuth(username, password))

                activereport.operstate = 'active'
                objs.append(activereport)
        elif deletion:
            # Apply Deletion Semantics:
            logger.debug("Applying Deletion Semanctics")
            # TODO: Figure out the odd scenario of Service deletion
            deletedobjs = VnodLocalService.deleted_objects.all()
            objs.extend(deletedobjs)

        # Finally just return the set of changed objects
        return objs

    def get_vnodlocal_system(self):
        # We only expect to have one of these objects in the system in the curent design
        # So get the first element from the query
        vnodlocalsystems = VnodLocalSystem.objects.all()
        if not vnodlocalsystems:
            return None

        return vnodlocalsystems[0]

    def get_autoattachhandles(self, vnodlocalsystem):
        # Figure out API call to actually get this to work
        rest_url = vnodlocalsystem.restUrl
        sitename = vnodlocalsystem.name
        username=vnodlocalsystem.username
        password=vnodlocalsystem.password
        query = {"sitename":sitename}


        resp = requests.get("{}/vnodglobal_api_autoattach/".format(rest_url), params=query,
                            auth=HTTPBasicAuth(username, password))

        handles = []
        if resp.status_code == 200:
            resp = resp.json()
            handles = resp['servicehandles']
        else:
            logger.debug("Request for autoattach servicehandles failed.")

        return handles

    def get_autoattachconfigured(self):
        # Query for the set of auto-attached handles that are  in the 'Configured' state
        autoattachedconfigured = VnodLocalService.objects.filter(autoattached=True, administrativeState='configured')

        if not autoattachedconfigured:
            return []

        return autoattachedconfigured


    def sync_record(self, o):

        # Simply save the record to the DB - both updates and adds are handled the same way
        o.save()


    def delete_record(self, o):
        # Overriden to customize our behaviour - the core sync step for will remove the record directly
        # We just log and return
        logger.debug("deleting Object %s" % str(o), extra=o.tologdict())

