#**************************************************************
#  
#  Licensed to the Apache Software Foundation (ASF) under one
#  or more contributor license agreements.  See the NOTICE file
#  distributed with this work for additional information
#  regarding copyright ownership.  The ASF licenses this file
#  to you 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 uno
import pyuno
import os
import sys

from com.sun.star.lang import XTypeProvider, XSingleComponentFactory, XServiceInfo
from com.sun.star.uno import RuntimeException, XCurrentContext
from com.sun.star.beans.MethodConcept import ALL as METHOD_CONCEPT_ALL
from com.sun.star.beans.PropertyConcept import ALL as PROPERTY_CONCEPT_ALL

from com.sun.star.reflection.ParamMode import \
     IN as PARAM_MODE_IN, \
     OUT as PARAM_MODE_OUT, \
     INOUT as PARAM_MODE_INOUT

from com.sun.star.beans.PropertyAttribute import \
     MAYBEVOID as PROP_ATTR_MAYBEVOID, \
     BOUND as PROP_ATTR_BOUND, \
     CONSTRAINED as PROP_ATTR_CONSTRAINED, \
     TRANSIENT as PROP_ATTR_TRANSIENT, \
     READONLY as PROP_ATTR_READONLY, \
     MAYBEAMBIGUOUS as PROP_ATTR_MAYBEAMBIGUOUS, \
     MAYBEDEFAULT as PROP_ATTR_MAYBEDEFAULT, \
     REMOVEABLE as PROP_ATTR_REMOVEABLE

def _mode_to_str( mode ):
    ret = "[]"
    if mode == PARAM_MODE_INOUT:
        ret = "[inout]"
    elif mode == PARAM_MODE_OUT:
        ret = "[out]"
    elif mode == PARAM_MODE_IN:
        ret = "[in]"
    return ret

def _propertymode_to_str( mode ):
    ret = ""
    if PROP_ATTR_REMOVEABLE & mode:
        ret = ret + "removeable "
    if PROP_ATTR_MAYBEDEFAULT & mode:
        ret = ret + "maybedefault "
    if PROP_ATTR_MAYBEAMBIGUOUS & mode:
        ret = ret + "maybeambigous "
    if PROP_ATTR_READONLY & mode:
        ret = ret + "readonly "
    if PROP_ATTR_TRANSIENT & mode:
        ret = ret + "tranient "
    if PROP_ATTR_CONSTRAINED & mode:
        ret = ret + "constrained "
    if PROP_ATTR_BOUND & mode:
        ret = ret + "bound "
    if PROP_ATTR_MAYBEVOID & mode:
        ret = ret + "maybevoid "
    return ret.rstrip()

def inspect( obj , out ):
    if isinstance( obj, uno.Type ) or \
       isinstance( obj, uno.Char ) or \
       isinstance( obj, uno.Bool ) or \
       isinstance( obj, uno.ByteSequence ) or \
       isinstance( obj, uno.Enum ) or \
       isinstance( obj, uno.Any ):
        out.write( str(obj) + "\n")
        return

    ctx = uno.getComponentContext()
    introspection = \
         ctx.ServiceManager.createInstanceWithContext( "com.sun.star.beans.Introspection", ctx )

    out.write( "Supported services:\n" )
    if hasattr( obj, "getSupportedServiceNames" ):
        names = obj.getSupportedServiceNames()
        for ii in names:
            out.write( "  " + ii + "\n" )
    else:
        out.write( "  unknown\n" )

    out.write( "Interfaces:\n" )
    if hasattr( obj, "getTypes" ):
        interfaces = obj.getTypes()
        for ii in interfaces:
            out.write( "  " + ii.typeName + "\n" )
    else:
        out.write( "  unknown\n" )

    access = introspection.inspect( obj )
    methods = access.getMethods( METHOD_CONCEPT_ALL )
    out.write( "Methods:\n" )
    for ii in methods:
        out.write( "  " + ii.ReturnType.Name + " " + ii.Name )
        args = ii.ParameterTypes
        infos = ii.ParameterInfos
        out.write( "( " )
        for i in range( 0, len( args ) ):
            if i > 0:
                out.write( ", " )
            out.write( _mode_to_str( infos[i].aMode ) + " " + args[i].Name + " " + infos[i].aName )
        out.write( " )\n" )

    props = access.getProperties( PROPERTY_CONCEPT_ALL )
    out.write ("Properties:\n" )
    for ii in props:
        out.write( "  ("+_propertymode_to_str( ii.Attributes ) + ") "+ii.Type.typeName+" "+ii.Name+ "\n" )

def createSingleServiceFactory( clazz, implementationName, serviceNames ):
    return _FactoryHelper_( clazz, implementationName, serviceNames )

class _ImplementationHelperEntry:
    def __init__(self, ctor,serviceNames):
        self.ctor = ctor
        self.serviceNames = serviceNames

class ImplementationHelper:
    def __init__(self):
        self.impls = {}

    def addImplementation( self, ctor, implementationName, serviceNames ):
        self.impls[implementationName] =  _ImplementationHelperEntry(ctor,serviceNames)

    def writeRegistryInfo( self, regKey, smgr ):
        for i in list(self.impls.items()):
            keyName = "/"+ i[0] + "/UNO/SERVICES"
            key = regKey.createKey( keyName )
            for serviceName in i[1].serviceNames:
                key.createKey( serviceName )
        return 1

    def getComponentFactory( self, implementationName , regKey, smgr ):
        entry = self.impls.get( implementationName, None )
        if entry == None:
            raise RuntimeException( implementationName + " is unknown" , None )
        return createSingleServiceFactory( entry.ctor, implementationName, entry.serviceNames )

    def getSupportedServiceNames( self, implementationName ):
        entry = self.impls.get( implementationName, None )
        if entry == None:
            raise RuntimeException( implementationName + " is unknown" , None )
        return entry.serviceNames

    def supportsService( self, implementationName, serviceName ):
        entry = self.impls.get( implementationName,None )
        if entry == None:
            raise RuntimeException( implementationName + " is unknown", None )
        return serviceName in entry.serviceNames


class ImplementationEntry:
    def __init__(self, implName, supportedServices, clazz ):
        self.implName = implName
        self.supportedServices = supportedServices
        self.clazz = clazz

def writeRegistryInfoHelper( smgr, regKey, seqEntries ):
    for entry in seqEntries:
        keyName = "/"+ entry.implName + "/UNO/SERVICES"
        key = regKey.createKey( keyName )
        for serviceName in entry.supportedServices:
            key.createKey( serviceName )

def systemPathToFileUrl( systemPath ):
    "returns a file-url for the given system path"
    return pyuno.systemPathToFileUrl( systemPath )

def fileUrlToSystemPath( url ):
    "returns a system path (determined by the system, the python interpreter is running on)"
    return pyuno.fileUrlToSystemPath( url )

def absolutize( path, relativeUrl ):
    "returns an absolute file url from the given urls"
    return pyuno.absolutize( path, relativeUrl )

def getComponentFactoryHelper( implementationName, smgr, regKey, seqEntries ):
    for x in seqEntries:
        if x.implName == implementationName:
            return createSingleServiceFactory( x.clazz, implementationName, x.supportedServices )

def addComponentsToContext( toBeExtendedContext, contextRuntime, componentUrls, loaderName ):
    smgr = contextRuntime.ServiceManager
    loader = smgr.createInstanceWithContext( loaderName, contextRuntime )
    implReg = smgr.createInstanceWithContext( "com.sun.star.registry.ImplementationRegistration",contextRuntime)

    isWin = os.name == 'nt' or os.name == 'dos'
    isMac = sys.platform == 'darwin'
    #   create a temporary registry
    for componentUrl in componentUrls:
        reg = smgr.createInstanceWithContext( "com.sun.star.registry.SimpleRegistry", contextRuntime )
        reg.open( "", 0, 1 )
        if not isWin and componentUrl.endswith( ".uno" ):  # still allow platform independent naming
            if isMac:
                componentUrl = componentUrl + ".dylib"
            else:
                componentUrl = componentUrl + ".so"

        implReg.registerImplementation( loaderName,componentUrl, reg )
        rootKey = reg.getRootKey()
        implementationKey = rootKey.openKey( "IMPLEMENTATIONS" )
        implNames = implementationKey.getKeyNames()
        extSMGR = toBeExtendedContext.ServiceManager
        for x in implNames:
            fac = loader.activate( max(x.split("/")),"",componentUrl,rootKey)
            extSMGR.insert( fac )
        reg.close()

# never shrinks !
_g_typeTable = {}
def _unohelper_getHandle( self):
    ret = None
    if self.__class__ in _g_typeTable:
        ret = _g_typeTable[self.__class__]
    else:
        names = {}
        traverse = list(self.__class__.__bases__)
        while len( traverse ) > 0:
            item = traverse.pop()
            bases = item.__bases__
            if uno.isInterface( item ):
                names[item.__pyunointerface__] = None
            elif len(bases) > 0:
                # the "else if", because we only need the most derived interface
                traverse = traverse + list(bases)#

        lst = list(names.keys())
        types = []
        for x in lst:
            t = uno.getTypeByName( x )
            types.append( t )

        ret = tuple(types) , uno.generateUuid()
        _g_typeTable[self.__class__] = ret
    return ret

class Base(XTypeProvider):
    def getTypes( self ):
        return _unohelper_getHandle( self )[0]
    def getImplementationId(self):
        return _unohelper_getHandle( self )[1]

class CurrentContext(XCurrentContext, Base ):
    """a current context implementation, which first does a lookup in the given
       hashmap and if the key cannot be found, it delegates to the predecessor
       if available
    """
    def __init__( self, oldContext, hashMap ):
        self.hashMap = hashMap
        self.oldContext = oldContext

    def getValueByName( self, name ):
        if name in self.hashMap:
            return self.hashMap[name]
        elif self.oldContext != None:
            return self.oldContext.getValueByName( name )
        else:
            return None

# -------------------------------------------------
# implementation details
# -------------------------------------------------
class _FactoryHelper_( XSingleComponentFactory, XServiceInfo, Base ):
    def __init__( self, clazz, implementationName, serviceNames ):
        self.clazz = clazz
        self.implementationName = implementationName
        self.serviceNames = serviceNames

    def getImplementationName( self ):
        return self.implementationName

    def supportsService( self, ServiceName ):
        return ServiceName in self.serviceNames

    def getSupportedServiceNames( self ):
        return self.serviceNames

    def createInstanceWithContext( self, context ):
        return self.clazz( context )

    def createInstanceWithArgumentsAndContext( self, args, context ):
        return self.clazz( context, *args )
