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

from __future__ import print_function
import argparse
import base64
import functools
import grpc
import orm
import os
import sys

from twisted.internet import reactor
from google.protobuf.empty_pb2 import Empty
from grpc import (
    metadata_call_credentials,
    composite_channel_credentials,
    ssl_channel_credentials,
)

# fix up sys.path for chameleon
import inspect

currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
sys.path = [currentdir] + sys.path

from xosconfig import Config
import chameleon_client.grpc_client as chameleon_client

from multistructlog import create_logger
log = create_logger(Config().get("logging"))

SERVER_CA = "/usr/local/share/ca-certificates/local_certs.crt"


class UsernamePasswordCallCredentials(grpc.AuthMetadataPlugin):
    """Metadata wrapper for raw access token credentials."""

    def __init__(self, username, password):
        self._username = username
        self._password = password

    def __call__(self, context, callback):
        basic_auth = "Basic %s" % base64.b64encode(
            "%s:%s" % (self._username, self._password)
        )
        metadata = (("authorization", basic_auth),)
        callback(metadata, None)


class SessionIdCallCredentials(grpc.AuthMetadataPlugin):
    """Metadata wrapper for raw access token credentials."""

    def __init__(self, sessionid):
        self._sessionid = sessionid

    def __call__(self, context, callback):
        metadata = (("x-xossession", self._sessionid),)
        callback(metadata, None)


class XOSClient(chameleon_client.GrpcClient):
    # We layer our own reconnect_callback functionality so we can setup the
    # ORM before calling reconnect_callback.

    def set_reconnect_callback(self, reconnect_callback):
        self.reconnect_callback2 = reconnect_callback

        return self

    def load_convenience_methods(self):

        convenience_methods_dir = (
            "/usr/local/lib/python2.7/dist-packages/xosapi/convenience/"
        )

        try:
            response = self.dynamicload.GetConvenienceMethods(Empty())

            if response:
                log.info(
                    "Loading convenience methods",
                    methods=[m.filename for m in response.convenience_methods],
                )

                for cm in response.convenience_methods:
                    log.debug("Saving convenience method", method=cm.filename)
                    save_path = os.path.join(convenience_methods_dir, cm.filename)
                    file(save_path, "w").write(cm.contents)
            else:
                log.exception(
                    "Cannot load convenience methods, restarting the synchronzier"
                )
                os.execv(sys.executable, ["python"] + sys.argv)

        except grpc._channel._Rendezvous as e:
            code = e.code()
            if code == grpc.StatusCode.UNAVAILABLE:
                # NOTE if the core is not available, restart the synchronizer
                os.execv(sys.executable, ["python"] + sys.argv)

    def reconnected(self):
        for api in ["modeldefs", "utility", "xos", "dynamicload"]:
            pb2_file_name = os.path.join(self.work_dir, api + "_pb2.py")
            pb2_grpc_file_name = os.path.join(self.work_dir, api + "_pb2_grpc.py")

            if os.path.exists(pb2_file_name) and os.path.exists(pb2_grpc_file_name):
                orig_sys_path = sys.path
                try:
                    sys.path.append(self.work_dir)
                    m_protos = __import__(api + "_pb2")
                    # reload(m_protos)
                    m_grpc = __import__(api + "_pb2_grpc")
                    # reload(m_grpc)
                finally:
                    sys.path = orig_sys_path

                stub_class = getattr(m_grpc, api + "Stub")

                setattr(self, api, stub_class(self.channel))
                setattr(self, api + "_pb2", m_protos)
            else:
                print("failed to locate api", api, file=sys.stderr)

        if hasattr(self, "xos"):
            self.xos_orm = orm.ORMStub(self.xos, self.xos_pb2, "xos")

        # ask the core for the convenience methods
        self.load_convenience_methods()

        # Load convenience methods after reconnect
        orm.import_convenience_methods()

        if self.reconnect_callback2:
            self.reconnect_callback2()


class InsecureClient(XOSClient):
    def __init__(
        self,
        consul_endpoint=None,
        work_dir="/tmp/xos_grpc_protos",
        endpoint="localhost:50055",
        reconnect_callback=None,
    ):
        super(InsecureClient, self).__init__(
            consul_endpoint, work_dir, endpoint, self.reconnected
        )

        self.reconnect_callback2 = reconnect_callback


class SecureClient(XOSClient):
    def __init__(
        self,
        consul_endpoint=None,
        work_dir="/tmp/xos_grpc_protos",
        endpoint="localhost:50055",
        reconnect_callback=None,
        cacert=SERVER_CA,
        username=None,
        password=None,
        sessionid=None,
    ):
        server_ca = open(cacert, "r").read()
        if sessionid:
            call_creds = metadata_call_credentials(SessionIdCallCredentials(sessionid))
        else:
            call_creds = metadata_call_credentials(
                UsernamePasswordCallCredentials(username, password)
            )
        chan_creds = ssl_channel_credentials(server_ca)
        chan_creds = composite_channel_credentials(chan_creds, call_creds)

        super(SecureClient, self).__init__(
            consul_endpoint, work_dir, endpoint, self.reconnected, chan_creds
        )

        self.reconnect_callback2 = reconnect_callback


# -----------------------------------------------------------------------------
# Wrappers for easy setup for test cases, etc
# -----------------------------------------------------------------------------


def parse_args():
    parser = argparse.ArgumentParser()

    defs = {
        "grpc_insecure_endpoint": "xos-core.cord.lab:50055",
        "grpc_secure_endpoint": "xos-core.cord.lab:50051",
        "config": "/opt/xos/config.yml",
    }

    _help = "Path to the config file (default: %s)" % defs["config"]
    parser.add_argument(
        "-C",
        "--config",
        dest="config",
        action="store",
        default=defs["config"],
        help=_help,
    )

    _help = (
        "gRPC insecure end-point to connect to. It is a direct",
        ". (default: %s" % defs["grpc_insecure_endpoint"],
    )
    parser.add_argument(
        "-G",
        "--grpc-insecure-endpoint",
        dest="grpc_insecure_endpoint",
        action="store",
        default=defs["grpc_insecure_endpoint"],
        help=_help,
    )

    _help = (
        "gRPC secure end-point to connect to. It is a direct",
        ". (default: %s" % defs["grpc_secure_endpoint"],
    )
    parser.add_argument(
        "-S",
        "--grpc-secure-endpoint",
        dest="grpc_secure_endpoint",
        action="store",
        default=defs["grpc_secure_endpoint"],
        help=_help,
    )

    parser.add_argument(
        "-u", "--username", dest="username", action="store", default=None, help=_help
    )

    parser.add_argument(
        "-p", "--password", dest="password", action="store", default=None, help=_help
    )

    _help = "omit startup banner log lines"
    parser.add_argument(
        "-n",
        "--no-banner",
        dest="no_banner",
        action="store_true",
        default=False,
        help=_help,
    )

    _help = "suppress debug and info logs"
    parser.add_argument("-q", "--quiet", dest="quiet", action="count", help=_help)

    _help = "enable verbose logging"
    parser.add_argument("-v", "--verbose", dest="verbose", action="count", help=_help)

    args = parser.parse_args()

    return args


def coreclient_reconnect(client, reconnect_callback, *args, **kwargs):
    global coreapi

    coreapi = coreclient.xos_orm

    if reconnect_callback:
        reconnect_callback(*args, **kwargs)

    reactor.stop()


def start_api(reconnect_callback, *args, **kwargs):
    global coreclient

    if kwargs.get("username", None):
        coreclient = SecureClient(*args, **kwargs)
    else:
        coreclient = InsecureClient(*args, **kwargs)

    coreclient.set_reconnect_callback(
        functools.partial(coreclient_reconnect, coreclient, reconnect_callback)
    )
    coreclient.start()

    reactor.run()


def start_api_parseargs(reconnect_callback):
    """ This function is an entrypoint for tests and other simple programs to
        setup the API and get a callback when the API is ready.
    """

    args = parse_args()

    if args.username:
        start_api(
            reconnect_callback,
            endpoint=args.grpc_secure_endpoint,
            username=args.username,
            password=args.password,
        )
    else:
        start_api(reconnect_callback, endpoint=args.grpc_insecure_endpoint)


# -----------------------------------------------------------------------------
# Self test
# -----------------------------------------------------------------------------


def insecure_callback(client):
    print("insecure self_test start")
    print(client.xos_orm.User.objects.all())
    print("insecure self_test done")

    # now start the next test
    client.stop()
    reactor.callLater(0, start_secure_test)


def start_insecure_test():
    client = InsecureClient(endpoint="xos-core:50055")
    client.set_reconnect_callback(functools.partial(insecure_callback, client))
    client.start()


def secure_callback(client):
    print("secure self_test start")
    print(client.xos_orm.User.objects.all())
    print("secure self_test done")
    reactor.stop()


def start_secure_test():
    client = SecureClient(
        endpoint="xos-core:50051", username="admin@opencord.org", password="letmein"
    )
    client.set_reconnect_callback(functools.partial(secure_callback, client))
    client.start()


def main():
    reactor.callLater(0, start_insecure_test)

    reactor.run()


if __name__ == "__main__":
    main()
