from Translator import  *

import DeclarationList
import Declaration
import SelectorList
import Property

import pdb

class SSSObject(Declaration.SSSDeclaration):

    UNKNOWN_RULE = 0
    STYLE_RULE = 1
    CHARSET_RULE = 2
    IMPORT_RULE = 3
    MEDIA_RULE = 4
    FONT_FACE_RULE = 5
    PAGE_RULE = 6
    
    #// Extensions...
    COMMENT_RULE = 7
    INCLUDE_RULE = 8
    INHERIT_RULE = 9
    CONSTANT_RULE = 10
    COPY_RULE = 11

    def __init__(self):

        super(SSSObject, self).__init__()

        self._declarations = DeclarationList.SSSDeclarationList(self)
        
        self._selector_lookup = {}

    def deleteRule(self, index): 
    
        return self._declarations._deleteRule(index)
    
    def insertRule(self, rule, index): 
    
        return self._declarations.insertItem(rule, index)
    
    def appendRule(self, rule):
            
        return self._declarations.appendItem(rule)
    
    #/* begin property functions */
    
    def getPropertyText(self):

        string = ''
        
        for key, item in self.items:
                    
            if (get_class(item) == 'SSSProperty'):
            
             string += "\t" + item.cssText

        return string

    def getRuleText(self):

        string = ''
        
        for key, item in self.items.items():

            if (get_class(item) != 'SSSProperty'):

                string += item.cssText

        return string


    def _parse(self, text):

        ruleText = ''

        sourceText = text

        stack = []
        
        incomment = False
        
        for i in xrange(len(sourceText)):

            char = sourceText[i]
            if  char == '/' and i != len(sourceText) - 1 and sourceText[i + 1] == '*':
                incomment = True
                continue
            elif char == '/' and sourceText[i - 1] == '*':
                incomment = False
                continue
                
            if not incomment:
                ruleText += char

                if (char == '{'):
    
                    stack.append(char)
    
                elif (char == '}'):
    
                    array_pop(stack)
    
                    if (len(stack) == 0):
    
                        self.append(ruleText)
    
                        ruleText = ''
    
                elif (char == ';') and (len(stack) == 0):
    
                    self.append(ruleText)
                    
                    ruleText = ''


    def getPropertyCSSValue(self, propertyName):

        prop_name = trim(propertyName)
        #pdb.set_trace()
        counter = self._declarations.length - 1
        while counter >= 0:
            item = self._declarations.item(counter)
            
            if get_class(item) == 'SSSProperty' and item.name == prop_name:

                return item
            elif get_class(item) == 'SSSIncludeRule' or get_class(item) == 'SSSImportRule':
                included_imported_property = item.getPropertyCSSValue(propertyName)
                if (included_imported_property):

                    return included_imported_property            
            counter -= 1
            
        return None       



    def inherit(self, selectorList, rule):
        
        for i in xrange(len(selectorList)): #(i = 0;  i < selectorList.length; i++):

            selector_to_inherit = selectorList.item(i)

            matches = self.getRulesWithSelector(selector_to_inherit)

            #foreach(matches as matching_selector=>$matches):
            for matching_selector, match in matches.items():

                for i in xrange(len(rule.selectorList)):    #(i = 0;  i < rule.selectorList.length; i++):

                    rule_selector = rule.selectorList.item(i)

                    new_selector = preg_replace(trim(selector_to_inherit), ' ' + rule_selector + ' ' , ' ' + matching_selector + ' ')


    def addSelectorToStyleRules(self, selector, rules):

        for key, rule in rules.items():

            if (rule.parentStyleSheet.ownerRule.type != SSSObject.IMPORT_RULE):

                rule.addSelector(selector)

            else:
                self._inherit_offset += 1

                index = self.insertRule(rule, self._inherit_offset)

                new_rule =  self._declarations.item(index)

                new_rule.addSelector(selector)


            self.addSelectorReference(selector, rule)


    def inheritFromStyleRuleWithSelector(self, selectorList):
        
        for i in xrange(len(selectorList)):     #(i = 0;  i < selectorList.length; i++):

            self.inheritFromStyleRuleWithSelector(selectorList.item(i))

        return

    def addInheritance(self, selector, child_selector):
        matches = self.getRulesWithSelector(selector)


        #foreach(matches as matching_selector=>rules):
        for matching_selector, rules in matches.items():

            new_selector = preg_replace(trim(selector), trim(child_selector), matching_selector)
            
            self.addSelectorToStyleRules(new_selector, rules)


    def getPropertyValue(self, propertyName):

        item = self.getPropertyCSSValue(propertyName)    
        if (item):

            return item.value

        return None
    
    
    
    def setProperty(self, propertyName, value, priority = ''):
        item = self.getPropertyCSSValue(propertyName)
        if (item): #// property currently exists...
        
            item.setValue(value)

        return self.appendItem(obj)


    def getRulesWithSelector(self, selector):

        matches = []

        selector = trim(selector)
        
        for selectorText, rules in self._selector_lookup.items():

            if preg_match('[\s]+' + selector + '[\s]+', ' ' + selectorText + ' '):

                for rule in rules:

                    matches.append(rule)

        return matches

    def getRulesBySelector(self, selector):
        try:
            return self._selector_lookup[trim(selector)]
        except KeyError:
            return []

    def copyFromRulesWithSelectors(self, selectors):
        
        selectorList = SelectorList.SSSSelectorList()

        selectors = selectorList.getSelectorsAsArray(selectors)

        for selector in selectors:

            self.copyFromRulesWithSelector(selector)


    def copyFromRulesWithSelector(self, selector):
    
        rules = self.hostStyleSheet.getRulesBySelector(selector)

        for rule in rules:
        
            self.copyFromRule(rule)

    def copyFromRule(self, rule):

        props = rule.getPropertiesAsArray()

        for prop in props:

            prop_object = Property.SSSProperty()
            
            self.addDeclaration(prop_object)

            prop_object.cssText = prop.cssText

    def addSelectorReferences(self, rule):

        import SelectorList

        selectorList = SelectorList.SSSSelectorList()

        selectors_array = selectorList.getSelectorsAsArray(rule.selectorText)

        for selector in selectors_array:
        
            self.addSelectorReference(selector, rule)

    def addSelectorReference(self, selector, rule):
        try:
            self._selector_lookup[trim(selector)].append(rule)
        except KeyError:
            self._selector_lookup[trim(selector)] = []
            self._selector_lookup[trim(selector)].append(rule)
        if self.parentObject:
            self.parentObject.addSelectorReference(selector, rule)
        
    def getPropertiesAsArray(self):

        props = []
        
        for i in xrange(self._declarations.length):

            item  = self._declarations.item(i)

            if (get_class(item) == 'SSSProperty'):

                props.append(item)

        return props


    def getStyleRulesAsArray(self):

        props = []
        
        for i in xrange(self._declarations.length):

            item  = self._declarations.item(i)
                    
            if (get_class(item) == 'SSSStyleRule'):

                props.append(item)

        return props


    def getNonStyleRulesAsArray(self):

        props = []

        addLogMessage('self._declarations.length = ' + str(self._declarations.length))

        for i in xrange(self._declarations.length):   #(i = 0; i < self._declarations.length; i++):

            item  = self._declarations.item(i)

            if (get_class(item) != 'SSSStyleRule'):

                props.append(item)

        return props


    def getCssTextFromArray(self, objects):

        cssText = ''

        for obj in objects:

            cssText += obj.cssText

        return cssText


    def addDeclaration(self, obj):

        self._declarations.appendItem(obj)

        obj._setParentObject(self)
    
        return obj


    def isDirective(self, cssText):

        matches = preg_match(r'^(\@[\S]*)', trim(cssText))
        
        if (matches):


            return matches[0]

        return False


    def append(self, cssText):

        directive = self.isDirective(cssText)
        if (directive):
                    
            if directive == '@charset':
                return self.addCharsetRule(cssText)

            elif directive == '@font-face':
                return self.addFontFaceRule(cssText)

                            
            elif directive == '@import':
                return self.addImportRule(cssText)


            elif directive == '@media':
                return self.addMediaRule(cssText)

            #// SSC Extensions...
            elif directive == '@inherit':
                return self.addInheritRule(cssText)


            elif directive == '@comment':
                return self.addCommentRule(cssText)


            elif directive == '@include':
                return self.addIncludeRule(cssText)
            
            elif directive == '@ignore':
                return self.addIgnoreRule(cssText)


            elif directive == '@constant':
                return self.addConstantRule(cssText)     


            elif directive == '@copy':
                return self.addCopyRule(cssText)            

        if preg_match(r'\;$', trim(cssText)):

            return self.addProperty(cssText)

        return self.addStyleRule(cssText)


    def addCharsetRule(self, cssText):
        import CharsetRule
        return self.addDeclaration(CharsetRule.SSSCharsetRule(cssText))
    
    def addFontFaceRule(self, cssText):
        return self.addDeclaration(SSSFontFaceRule(cssText))
    
    def addImportRule(self, cssText):
        import ImportRule
        rule = self.addDeclaration(ImportRule.SSSImportRule())
        rule.cssText = cssText
        return rule

    def addMediaRule(self, cssText):
        import MediaRule
        rule = self.addDeclaration(MediaRule.SSSMediaRule())
        rule.cssText = cssText
        return rule
    
    def addInheritRule(self, cssText): 
        import InheritRule
        rule = self.addDeclaration(InheritRule.SSSInheritRule())
        rule.cssText = cssText
        return rule
    
    def addCommentRule(self, cssText): 
        import CommentRule
        rule = self.addDeclaration(CommentRule.SSSCommentRule(cssText))
        return rule
        
    def addIncludeRule(self, cssText):
        import IncludeRule
        rule = self.addDeclaration(IncludeRule.SSSIncludeRule())
        rule.cssText = cssText
        return rule
    
    def addIgnoreRule(self, cssText):
        import IgnoreRule
        rule = self.addDeclaration(IgnoreRule.SSSIgnoreRule())
        rule.cssText = cssText
        return rule
        
    def addConstantRule(self, cssText):
        import ConstantRule
        rule = self.addDeclaration(ConstantRule.SSSConstantRule())
        rule.cssText = cssText
        return rule
        
    def addCopyRule(self, cssText): 
        import CopyRule
        rule = self.addDeclaration(CopyRule.SSSCopyRule(cssText))
        self.copyFromRulesWithSelectors(rule.selectorText)
        return rule

    #// Style Rules:
    def addStyleRule(self, cssText):
        
        import StyleRule
        
        obj = self.addDeclaration(StyleRule.SSSStyleRule())
        
        obj.cssText = cssText

        if get_class(obj) == 'SSSStyleRule':

            #obj.prependToAllSelectors(self.selectorText)

            self.addSelectorReferences(obj)

        return obj


    def addStyleSheet(self, cssText = ''):

        obj = self.addDeclaration(StyleSheet.SSSStyleSheet())

        return obj


    def addProperty(self, cssText):

        import Property

        obj = self.addDeclaration(Property.SSSProperty())

        obj.cssText = cssText
        
        return obj

    def getVar(self, name):
        
        value = self.getPropertyValue(name)
        if (value):

            return value

        elif (self.parentObject):

            return self.parentObject.getVar(name)

        return False
    

    def __set(self, var, value):

        prop = self.__get(var)
        if prop:

            prop.value = value

        else:

            prop = SSSProperty()
            prop.name = var
            prop.value = value
            
            self._declarations.appendItem(prop)

    def get_length(self):
        if (self._declarations):
            return self._declarations.length
        return 0

    length = property(get_length)

    
