from rdflib import Graph
from rdflib import URIRef, Literal, BNode, Namespace
from rdflib import RDF, RDFS

import webcache
from pprint import pprint


class RDF_World:

    mcb2rdf_types = {"string" : 'string',
                     "number" : 'float',
                     "date" : 'dateTime',
                     "url" : 'anyURI',
                     'html' : 'string',
                     }
    
    def __init__(self, directory='.'):
        self.store = Graph()
        self.cache = webcache.WebCache(directory + "/pages.db",
                                       directory + "/times.db",
                                       24*60*60)  # Shared webpage cache
        
    def mcb2rdf_schema(self, schema):
        store = self.store
        id = schema.get('id')[0].strip()
        cls = URIRef("#" +id)
        store.add((cls, RDF.type, RDFS.Class))
        v = schema.get('label', [''])[0]
        if v:
            store.add((cls, RDFS.label, Literal(v)))
            
        for attribute in schema.get('attribute', []):
            key = attribute.get('key',[''])[0]
            if not key: continue
            print id + key
            attr = URIRef("#%s_%s" % (id, key))
            store.add((cls, RDFS.range, attr))
            store.add((attr,RDF.type, RDF.Property))
            label = attribute.get('label',[''])[0]
            if label:
                store.add((attr, RDFS.label, Literal(label)))

            description = attribute.get('description',[''])[0]
            if description:
                store.add((attr, RDFS.comment, Literal(description)))

            #required = attribute.get('label',[0])[0]
            #if required:
            #    store.add((attr, "owl:minCardinaly", Literal(1)))

            #multiple = attribute.get('label',[0])[1]
            #if not multiple:
            #    store.add((attr, "owl:maxCardinaly", Literal(1)))

            type = attribute.get('type',[''])[0].strip()
            if self.mcb2rdf_types.has_key(type):
                store.add((attr, RDFS.Datatype,
                           Literal(self.mcb2rdf_types[type])))
            else:
                pass #XXX
                #    rdfs:range

            #"default" -> create entries


    def mcb2rdf(self, block):
        store = self.store
        b = BNode()
        
        for key, value in block.iteritems():
            if key=='type':
                pass
            else:
                pass

    def get_superclasses(self, cls, store):
        to_check = [cls]
        checked = []
        while to_check:
            check = to_check.pop()
            for cls in store.objects(check, RDFS.subClassOf):
                if cls not in to_check and not cls in checked:
                    to_check.append(cls)
            checked.append(check)
        return checked

    def get_properties(self, cls_list, store):
        properties = {u'about' : RDF.about}
        for cls in cls_list:
            for property in store.subjects(RDFS.domain, cls):
                local_name = property.split('#')
                if len(local_name)>1:
                    local_name = local_name[-1].strip()
                else:
                    local_name = property.split('/')[-1].lower()
                    if properties.has_key(local_name):
                        print "XXX", properties[local_name], "X", property
                properties[local_name] = property
        return properties

    def mcb_rdf(self, mcb):
        store = Graph()
        store.parse("http://www.w3.org/1999/02/22-rdf-syntax-ns")
        store.parse("http://www.w3.org/2000/01/rdf-schema")
        
        for url in mcb.get('RDFFILE'):
            #file = self.cache.get_page(url)
            store.parse(url.strip())

        cls = mcb.get("CLASS", [''])[0].strip()
        if not cls: return

        for cls_node in store.subjects(RDF.type, RDFS.Class):
            if cls_node.endswith(cls):
                cls = cls_node
                break
            
        print cls
        inst = URIRef(mcb._url) #XXX id
        self.store.add((inst, RDF.type, cls))
        
        superclasses = self.get_superclasses(cls, store)
        superclasses.append(RDFS.Resource)
        properties = self.get_properties(superclasses, store)
        pprint(superclasses)
        print
        pprint(properties)

        for key, values in mcb.iteritems():
            key = key.lower()
            if properties.has_key(key):
                property = properties[key]
                #for po in store.predicate_objects(property):
                #    print property, po
                # XXX check property type!
                for value in values:
                    self.store.add((inst, property, Literal(value)))
            else:
                 print key, "ignored X("
    

        print self.store.serialize(format="pretty-xml")
