
# 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.

import json
import requests
from requests.auth import HTTPBasicAuth
from synchronizers.new_base.syncstep import SyncStep, DeferredException, model_accessor
from synchronizers.new_base.modelaccessor import ONOSApp, ServiceInstance, ServiceInstanceAttribute

from xosconfig import Config
from multistructlog import create_logger

from helpers import Helpers

log = create_logger(Config().get('logging'))
log.info("config file", file=Config().get_config_file())

class SyncONOSApp(SyncStep):
    provides = [ONOSApp]
    observes = [ONOSApp, ServiceInstanceAttribute]

    def get_service_instance_attribute(self, o):
        # NOTE this method is defined in the core convenience methods for service_instances
        svc = ServiceInstance.objects.get(id=o.id)
        return svc.serviceinstanceattribute_dict

    def check_app_dependencies(self, deps):
        """
        Check if all the dependencies required by this application are installed
        :param deps: comma separated list of application names
        :return: bool
        """
        for dep in [x.strip() for x in str(deps).split(',') if x is not ""]:
            try:
                app = ONOSApp.objects.get(app_id=dep)
                if not app.backend_code == 1:
                    # backend_code == 1 means that the app has been pushed
                    return False
            except IndexError, e:
                return False
        return True

    def add_config(self, o):
        log.info("Adding config %s" % o.name, model=o.tologdict())
        # getting onos url and auth
        onos_url = "%s:%s" % (Helpers.format_url(o.service_instance.leaf_model.owner.leaf_model.rest_hostname), o.service_instance.leaf_model.owner.leaf_model.rest_port)
        onos_basic_auth = HTTPBasicAuth(o.service_instance.leaf_model.owner.leaf_model.rest_username, o.service_instance.leaf_model.owner.leaf_model.rest_password)

        # push configs (if any)
        url = o.name
        if url[0] == "/":
            # strip initial /
            url = url[1:]

        url = '%s/%s' % (onos_url, url)
        value = json.loads(o.value)
        request = requests.post(url, json=value, auth=onos_basic_auth)

        if request.status_code != 200:
            log.error("Request failed", response=request.text)
            raise Exception("Failed to add config %s in ONOS:  %s" % (url, request.text))

    def activate_app(self, o, onos_url, onos_basic_auth):
        log.info("Activating app %s" % o.app_id)
        url = '%s/onos/v1/applications/%s/active' % (onos_url, o.app_id)
        request = requests.post(url, auth=onos_basic_auth)

        if request.status_code != 200:
            log.error("Request failed", response=request.text)
            raise Exception("Failed to add application %s to ONOS: %s" % (url, request.text))

        url = '%s/onos/v1/applications/%s' % (onos_url, o.app_id)
        request = requests.get(url, auth=onos_basic_auth)

        if request.status_code != 200:
            log.error("Request failed", response=request.text)
            raise Exception("Failed to read application %s from ONOS: %s" % (url, request.text))
        else:
            o.version = request.json()["version"]

    def check_app_installed(self, o, onos_url, onos_basic_auth):
        url = '%s/onos/v1/applications/%s' % (onos_url, o.app_id)
        request = requests.get(url, auth=onos_basic_auth)

        if request.status_code == 200:
            if "version" in request.json() and o.version == request.json()["version"]:
                return True
            else:
                # uninstall the application
                self.uninstall_app(o, onos_url, onos_basic_auth)
                return False
        if request.status_code == 404:
            # app is not installed at all
            return False
        else:
            log.error("Request failed", response=request.text)
            raise Exception("Failed to read application %s from ONOS: %s" % (url, request.text))

    def install_app(self, o, onos_url, onos_basic_auth):
        log.info("Installing app from url %s" % o.url)

        # check is the already installed app is the correct version (if it has no app_id is not installed)
        is_installed = False
        if o.app_id and o.app_id is not None:
            is_installed = self.check_app_installed(o, onos_url, onos_basic_auth)

        if is_installed:
            # if the app is already installed we don't need to do anything
            return

        if not o.version or o.version is None:
            # TODO move this validation in the model.py (if the url is there version must there and app_id must not)
            raise Exception('You need to specify a version')
        data = {
            'activate': True,
            'url': o.url
        }
        url = '%s/onos/v1/applications' % onos_url
        request = requests.post(url, json=data, auth=onos_basic_auth)

        if request.status_code != 200:
            log.error("Request failed", response=request.text)
            raise Exception("Failed to add application %s to ONOS: %s" % (url, request.text))

        o.app_id = request.json()["name"]

        url = '%s/onos/v1/applications/%s' % (onos_url, o.app_id)
        request = requests.get(url, auth=onos_basic_auth)

        if request.status_code != 200:
            log.error("Request failed", response=request.text)
            raise Exception("Failed to read application %s from ONOS: %s" % (url, request.text))
        else:
            if o.version != request.json()["version"]:
                raise Exception("The version of %s you installed (%s) is not the same you requested (%s)" % (o.app_id, request.json()["version"], o.version))

    def sync_record(self, o):
        log.info("Sync'ing", model=o.tologdict())
        if hasattr(o, 'service_instance'):
            # this is a ServiceInstanceAttribute model just push the config
            if 'ONOSApp' in o.service_instance.leaf_model.class_names:
                return self.add_config(o)
            return # if it's not an ONOSApp do nothing

        if not self.check_app_dependencies(o.dependencies):
            raise DeferredException('Deferring installation of ONOSApp with id %s as dependencies are not met' % o.id)

        # getting onos url and auth
        onos_url = "%s:%s" % (Helpers.format_url(o.owner.leaf_model.rest_hostname), o.owner.leaf_model.rest_port)
        onos_basic_auth = HTTPBasicAuth(o.owner.leaf_model.rest_username, o.owner.leaf_model.rest_password)

        # activate app (bundled in onos)
        if not o.url or o.url is None:
            self.activate_app(o, onos_url, onos_basic_auth)
        # install an app from a remote source
        if o.url and o.url is not None:
            self.install_app(o, onos_url, onos_basic_auth)

    def delete_config(self, o):
        log.info("Deleting config %s" % o.name)
        # getting onos url and auth
        onos_app = o.service_instance.leaf_model
        onos_url = "%s:%s" % (Helpers.format_url(onos_app.owner.leaf_model.rest_hostname), onos_app.owner.leaf_model.rest_port)
        onos_basic_auth = HTTPBasicAuth(onos_app.owner.leaf_model.rest_username, onos_app.owner.leaf_model.rest_password)

        url = o.name
        if url[0] == "/":
            # strip initial /
            url = url[1:]

        url = '%s/%s' % (onos_url, url)
        request = requests.delete(url, auth=onos_basic_auth)

        if request.status_code != 204:
            log.error("Request failed", response=request.text)
            raise Exception("Failed to remove config %s from ONOS:  %s" % (url, request.text))

    def uninstall_app(self,o, onos_url, onos_basic_auth):
        log.info("Uninstalling app %s" % o.app_id)
        url = '%s/onos/v1/applications/%s' % (onos_url, o.app_id)

        request = requests.delete(url, auth=onos_basic_auth)

        if request.status_code != 204:
            log.error("Request failed", response=request.text)
            raise Exception("Failed to delete application %s from ONOS: %s" % (url, request.text))

    def deactivate_app(self, o, onos_url, onos_basic_auth):
        log.info("Deactivating app %s" % o.app_id)
        url = '%s/onos/v1/applications/%s/active' % (onos_url, o.app_id)

        request = requests.delete(url, auth=onos_basic_auth)

        if request.status_code != 204:
            log.error("Request failed", response=request.text)
            raise Exception("Failed to deactivate application %s from ONOS: %s" % (url, request.text))

    def delete_record(self, o):

        if hasattr(o, 'service_instance'):
            # this is a ServiceInstanceAttribute model
            if 'ONOSApp' in o.service_instance.leaf_model.class_names:
                return self.delete_config(o)
            return # if it's not related to an ONOSApp do nothing

        # NOTE if it is an ONOSApp we don't care about the ServiceInstanceAttribute
        # as the reaper will delete it

        # getting onos url and auth
        onos_url = "%s:%s" % (Helpers.format_url(o.owner.leaf_model.rest_hostname), o.owner.leaf_model.rest_port)
        onos_basic_auth = HTTPBasicAuth(o.owner.leaf_model.rest_username, o.owner.leaf_model.rest_password)

        # deactivate an app (bundled in onos)
        if not o.url or o.url is None:
            self.deactivate_app(o, onos_url, onos_basic_auth)
        # uninstall an app from a remote source, only if it has been activated before
        if o.url and o.url is not None:
            self.uninstall_app(o, onos_url, onos_basic_auth)
