#
# Copyright 2017 the original author or authors.
#
# 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.
#

"""gRPC server endpoint"""
import os
import uuid
from Queue import Queue
from collections import OrderedDict
from os.path import abspath, basename, dirname, join, walk
import grpc
from concurrent import futures
from structlog import get_logger
import zlib

from zope.interface import implementer

from common.utils.grpc_utils import twisted_async
from voltha.core.logical_device_agent import LogicalDeviceAgent
from voltha.protos import voltha_pb2, schema_pb2
from google.protobuf.empty_pb2 import Empty

from voltha.registry import IComponent

log = get_logger()


class SchemaService(schema_pb2.SchemaServiceServicer):

    def __init__(self, thread_pool):
        self.thread_pool = thread_pool
        protos = self._load_schema()
        self.schemas = schema_pb2.Schemas(protos=protos,
                                          swagger_from='voltha.proto',
                                          yang_from='voltha.proto')

    def stop(self):
        pass

    def _load_schema(self):
        """Pre-load schema file so that we can serve it up (file sizes
           are small enough to do so
        """
        proto_dir = abspath(join(dirname(__file__), '../../protos'))

        def find_files(dir, suffix):
            proto_files = [
                join(dir, fname) for fname in os.listdir(dir)
                if fname.endswith(suffix)
            ]
            return proto_files

        proto_map = OrderedDict()  # to have deterministic data
        for proto_file in find_files(proto_dir, '.proto'):
            with open(proto_file, 'r') as f:
                proto_content = f.read()
            fname = basename(proto_file)
            # assure no two files have the same basename
            assert fname not in proto_map

            desc_file = proto_file.replace('.proto', '.desc')
            with open(desc_file, 'r') as f:
                descriptor_content = zlib.compress(f.read())

            proto_map[fname] = schema_pb2.ProtoFile(
                file_name=fname,
                proto=proto_content,
                descriptor=descriptor_content
            )

        return proto_map.values()

    def GetSchema(self, request, context):
        """Return current schema files and descriptor"""
        return self.schemas


class HealthService(voltha_pb2.HealthServiceServicer):

    def __init__(self, thread_pool):
        self.thread_pool = thread_pool

    def stop(self):
        pass

    def GetHealthStatus(self, request, context):
        """Return current health status of a Voltha instance
        """
        log.info('get-health-status', request=request)
        res = voltha_pb2.HealthStatus(
            state=voltha_pb2.HealthStatus.HEALTHY
        )
        return res

'''
class VolthaLogicalLayer(voltha_pb2.VolthaLogicalLayerServicer):
    # TODO still a mock

    def __init__(self, threadpool):
        self.threadpool = threadpool
        self.devices = [LogicalDeviceAgent(self, 1)]
        self.devices_map = dict((d.info.id, d) for d in self.devices)
        self.packet_in_queue = Queue()

        self.stopped = False

    def stop(self):
        self.stopped = True

    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    # Note that all GRPC method implementations are not called on the main
    # (twisted) thread. We shall contain them here and not spread calls on
    # "foreign" threads elsewhere in the application. So all calls out from
    # these methods shall be called with the callFromThread pattern.
    # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @twisted_async
    def ListLogicalDevices(self, request, context):
        return voltha_pb2.LogicalDevices(
            items=[voltha_pb2.LogicalDevice(
                id=d.info.id,
                datapath_id=d.info.datapath_id,
                desc=d.info.desc
            ) for d in self.devices])

    @twisted_async
    def GetLogicalDevice(self, request, context):
        return self.devices_map[request.id].info

    @twisted_async
    def ListLogicalDevicePorts(self, request, context):
        device_model = self.devices_map[request.id]
        return voltha_pb2.LogicalPorts(items=device_model.ports)

    @twisted_async
    def UpdateFlowTable(self, request, context):
        device_model = self.devices_map[request.id]
        device_model.update_flow_table(request.flow_mod)
        return Empty()

    @twisted_async
    def ListDeviceFlows(self, request, context):
        device_model = self.devices_map[request.id]
        flows = device_model.list_flows()
        return voltha_pb2.Flows(items=flows)

    @twisted_async
    def UpdateGroupTable(self, request, context):
        device_model = self.devices_map[request.id]
        device_model.update_group_table(request.group_mod)
        return Empty()

    @twisted_async
    def ListDeviceFlowGroups(self, request, context):
        device_model = self.devices_map[request.id]
        groups = device_model.list_groups()
        return voltha_pb2.FlowGroups(items=groups)

    def StreamPacketsOut(self, request_iterator, context):

        @twisted_async
        def forward_packet_out(packet_out):
            device_model = self.devices_map[packet_out.id]
            device_model.packet_out(packet_out.packet_out)

        for request in request_iterator:
            forward_packet_out(packet_out=request)

        return Empty()

    def ReceivePacketsIn(self, request, context):
        while 1:
            packet_in = self.packet_in_queue.get()
            yield packet_in

    def send_packet_in(self, device_id, ofp_packet_in):
        """Must be called on the twisted thread"""
        packet_in = voltha_pb2.PacketIn(id=device_id, packet_in=ofp_packet_in)
        self.packet_in_queue.put(packet_in)
'''

@implementer(IComponent)
class VolthaGrpcServer(object):

    def __init__(self, port=50055):
        self.port = port
        log.info('init-grpc-server', port=self.port)
        self.thread_pool = futures.ThreadPoolExecutor(max_workers=10)
        self.server = grpc.server(self.thread_pool)
        self.services = []

    def start(self):
        log.debug('starting')

        # add each service unit to the server and also to the list
        for activator_func, service_class in (
            (schema_pb2.add_SchemaServiceServicer_to_server, SchemaService),
            (voltha_pb2.add_HealthServiceServicer_to_server, HealthService),
        ):
            service = service_class(self.thread_pool)
            self.register(activator_func, service)

        # open port
        self.server.add_insecure_port('[::]:%s' % self.port)

        # strat the server
        self.server.start()

        log.info('started')
        return self

    def stop(self, grace=0):
        log.debug('stopping')
        for service in self.services:
            service.stop()
        self.server.stop(grace)
        self.thread_pool.shutdown(False)
        log.info('stopped')

    def register(self, activator_func, service):
        """
        Allow late registration of gRPC servicers
        :param activator_func: The gRPC "add_XYZServicer_to_server method
        autogenerated by protoc.
        :param service: The object implementing the service.
        :return: None
        """
        self.services.append(service)
        activator_func(service, self.server)


# This is to allow running the GRPC server in stand-alone mode

if __name__ == '__main__':

    server = VolthaGrpcServer().start()

    import time
    _ONE_DAY_IN_SECONDS = 60 * 60 * 24
    try:
        while 1:
            time.sleep(_ONE_DAY_IN_SECONDS)
    except KeyboardInterrupt:
        server.stop()


