import os
import time

from lxml import etree

from partial.bundleComponent import CompilationException
from partial.coffee import CoffeeBundleComponent
from partial.sass import SassBundleComponent
from partial.templating import TemplateBundleComponent

COMPILERS = {
    'template': TemplateBundleComponent(),
    'sass': SassBundleComponent(),
    'coffee': CoffeeBundleComponent(),
}

class Bundle(object):

    def __init__(self, path, server):
        self.path = path
        self.name = os.path.split(path)[-1].replace(".part.xml", "")
        self.server = server
        self.megamodule = None
        self.compiled = {}
        self.component = {}
        self.requirements = []
        self.compile()

    def compile(self):
        self.compiled = {}
        self.component = {}

        try:
            tree = etree.parse(open(self.path))
        except Exception:
            print "failed parsing xml"
            return

        self.megamodule = tree.xpath('/partial/@megamodule')[0]

        for type in COMPILERS.keys():
            component = tree.xpath('/partial/%s/text()' % type)
            if component:
                rawSrc = component[0]
                compiled = self.compileComponent(type, rawSrc)
                if compiled:
                    self.compiled.append(compiled)

        self.requirements = self.computeRequirements(tree)

    def computeRequirements(self, tree):
        return set(tree.xpath('/partial/require/text()'))

    def compileComponent(self, type, src):
        start = time.time()
        if type in COMPILERS:
            compiler = COMPILERS[type]
        else:
            print "type not recognized"
            return

        try:
            self.component[type] = compiler.read(src, self.name, self.megamodule)
            if not self.server:
                self.compiled[type] = compiler.compile(self.component[type], self.name, self.megamodule)
                end = time.time()
                print "compiled %s %s in %s" % (self.name, type, (end-start))
        except CompilationException:
            print "compilation error!"

    def satisfied(self, available):
        for requirement in self.requirements:
            if requirement not in available:
                return False
        return True