# -*- coding: utf-8 -*-

# Copyright (c) 2004 - 2008 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing the builtin API generator.

"""

import sys

class APIGenerator(object):
    """
    Class implementing the builtin documentation generator.
    """
    def __init__(self, module):
        """
        Constructor
        
        @param module The information of the parsed Python file.
        """
        self.module = module
        
    def genAPI(self, newStyle, basePackage, includePrivate):
        """
        Method to generate the source code documentation.
        
        @param newStyle flag indicating the api generation for QScintilla 1.7 and 
            newer (boolean)
        @param basePackage name of the base package (string)
        @param includePrivate flag indicating to include 
            private methods/functions (boolean)
        @return The API information. (string)
        """
        self.includePrivate = includePrivate
        self.newStyle = newStyle
        if self.newStyle:
            modulePath = self.module.name.split('.')
            if modulePath[-1] == '__init__':
                del modulePath[-1]
            if basePackage:
                modulePath[0] = basePackage
            self.moduleName = "%s." % '.'.join(modulePath)
        else:
            self.moduleName = ""
        self.api = []
        self.__addGlobalsAPI()
        self.__addClassesAPI()
        self.__addFunctionsAPI()
        return self.api
        
    def __isPrivate(self, name):
        """
        Private method to check, if a name is considered private.
        
        @return flag indicating a name, that is considered private (boolean)
        """
        private = name.startswith('__') and not self.includePrivate
        return private
        
    def __addGlobalsAPI(self):
        """
        Private method to generate the api section for global variables. 
        """
        if self.newStyle:
            moduleNameStr = "%s" % self.moduleName
        else:
            moduleNameStr = ""
        
        for globalName in sorted(self.module.globals):
            if not self.__isPrivate(globalName):
                self.api.append("%s%s" % (moduleNameStr, globalName))
        
    def __addClassesAPI(self):
        """
        Private method to generate the api section for classes.
        """
        classNames = self.module.classes.keys()
        classNames.sort()
        for className in classNames:
            if not self.__isPrivate(className):
                self.__addClassVariablesAPI(className)
                self.__addMethodsAPI(className)
        
    def __addMethodsAPI(self, className):
        """
        Private method to generate the api section for class methods.
        
        @param classname Name of the class containing the method. (string)
        """
        _class = self.module.classes[className]
        methods = _class.methods.keys()
        methods.sort()
        
        # first do the constructor
        if '__init__' in methods:
            methods.remove('__init__')
            self.api.append('%s%s(%s)' % \
                (self.moduleName, _class.name, 
                 ', '.join(_class.methods['__init__'].parameters[1:])))
            self.api.append('%s%s.__init__(%s)' % \
                (self.moduleName, _class.name, 
                 ', '.join(_class.methods['__init__'].parameters)))
            
        if self.newStyle:
            classNameStr = "%s%s." % (self.moduleName, className)
        else:
            classNameStr = ""
        for method in methods:
            if not self.__isPrivate(method): 
                self.api.append('%s%s(%s)' % \
                    (classNameStr, method,
                     ', '.join(_class.methods[method].parameters[1:])))
        
    def __addClassVariablesAPI(self, className):
        """
        Private method to generate class api section for class variables.
        
        @param classname Name of the class containing the class variables. (string)
        """
        _class = self.module.classes[className]
        if self.newStyle:
            classNameStr = "%s%s." % (self.moduleName, className)
        else:
            classNameStr = ""
        for variable in sorted(_class.globals):
            if not self.__isPrivate(variable): 
                self.api.append('%s%s' % (classNameStr, variable))
        
    def __addFunctionsAPI(self):
        """
        Private method to generate the api section for functions.
        """
        funcNames = self.module.functions.keys()
        funcNames.sort()
        for funcName in funcNames:
            if not self.__isPrivate(funcName): 
                self.api.append('%s%s(%s)' % \
                    (self.moduleName, self.module.functions[funcName].name,
                     ', '.join(self.module.functions[funcName].parameters)))
