__all__= ['ASRServicer','init']

import grpc,threading,traceback
import logging as Log

import mllp_grpc.asr_pb2_grpc as asr_pb2_grpc
import mllp_grpc.asr_pb2 as asr_pb2
import mllp_grpc.asr_common_pb2 as asr_common_pb2
import google.protobuf.empty_pb2 as empty_pb2
import server_lib.decoder_multi as decoder_multi
from server_lib.decoder_mng import DecoderException

def ii_(func,txt,context):
    Log.info('[%s] (%s) %s'%(context.peer(),func,txt))
    
class ASRServicer(asr_pb2_grpc.ASRServicer):

    def __init__(self,mng):
        self._mng= mng

    def AddSystem(self,request,context):
        def ii(txt): ii_('AddSystem',txt,context)
        try:
            self._mng.add(request.host,request.port,ii)
            ii('added %s:%d'%(request.host,request.port))
            code= asr_pb2.AddSystemResponse.Code.OK
            return asr_pb2.AddSystemResponse(code=code)
        except Exception as e:
            msg= 'error adding system %s:%d: %s'%(request.host,
                                                  request.port,
                                                  str(e))
            ii(msg)
            code= asr_pb2.AddSystemResponse.Code.OK
            return asr_pb2.AddSystemResponse(code=code,
                                             details=msg)

    def GetSystemInfoById(self,request,context):
        def ii(txt): ii_('GetSystemInfoById',txt,context)
        ii("retrieving ASR system information for %s"%request.system_id)
        ok,info= self._mng.get_system_info(request.system_id,ii)
        if ok:
            return asr_pb2.GetSystemInfoByIdResponse(
                code=asr_pb2.GetSystemInfoByIdResponse.Code.OK,
                info=info.info,
                num_decoders=info.num_decoders,
                num_decoders_available=info.num_decoders_available,
                id=info.id)
        else:
            return asr_pb2.GetSystemInfoByIdResponse(
                code=asr_pb2.GetSystemInfoByIdResponse.Code.ERR)
        
    def GetSystemsInfo(self,request,context):
        def ii(txt): ii_('GetSystemsInfo',txt,context)
        ii('retrieving ASR systems information')
        for v in self._mng.get_systems_info(ii):
            yield asr_pb2.GetSystemsInfoResponse(
                info=v.info,
                num_decoders=v.num_decoders,
                num_decoders_available=v.num_decoders_available,
                id=v.id)

    def GetHostsInfo(self,request,context):
        def ii(txt): ii_('GetHostsInfo',txt,context)
        ii('retrieving hosts information')
        for v in self._mng.get_hosts_info(ii):
            yield asr_pb2.GetHostsInfoResponse(
                info=v.info,
                num_decoders=v.num_decoders,
                num_decoders_available=v.num_decoders_available,
                host=v.host,
                port=v.port)
            
    def Decode(self,request_iterator,context):
        def ii(txt): ii_('Decode',txt,context)
        try:
            for o in self._mng.decode(request_iterator,ii):
                yield o
        except DecoderException as e:
            ii(e.msg)
            status= asr_common_pb2.DecodeResponse.Status(code=e.code,
                                                         details=e.msg)
            yield asr_common_pb2.DecodeResponse(status=status)
        except BaseException as e:
            traceback.print_exc()
            ii(str(e))
            code= asr_common_pb2.DecodeResponse.Status.Code.ERR_RECO
            status= asr_common_pb2.DecodeResponse.Status(code=code,
                                                         details=str(e))
            yield asr_common_pb2.DecodeResponse(status=status)
        ii('Done!')

    def DecodeMulti(self,request_iterator,context):
        def ii(txt): ii_('DecodeMulti',txt,context)
        try:
            for o in decoder_multi.decode(self._mng,request_iterator,ii):
                yield o
        except DecoderException as e:
            ii(e.msg)
            status= asr_common_pb2.DecodeResponse.Status(code=e.code,
                                                         details=e.msg)
            res= asr_common_pb2.DecodeResponse(status=status)
            yield asr_pb2.DecodeMultiResponse(res=res)
        except BaseException as e:
            traceback.print_exc()
            ii(str(e))
            code= asr_common_pb2.DecodeResponse.Status.Code.ERR_RECO
            status= asr_common_pb2.DecodeResponse.Status(code=code,
                                                         details=str(e))
            res= asr_common_pb2.DecodeResponse(status=status)
            yield asr_pb2.DecodeMultiResponse(res=res)
        ii('Done!')
        
def init(server,mng):
    asr_pb2_grpc.add_ASRServicer_to_server(
        ASRServicer(mng),server)
    
