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


class project():

    def __init__(self, IfcProject, g, ontology, resource):
        self.IfcProject = IfcProject
        self.g = g
        self.ontology = ontology
        self.resource = resource

    def ifcProjectFunction(self):
        for proj in self.IfcProject:
            projectID = proj['globalId']
            #basic information
            self.g.add((self.resource[projectID], RDF.type, self.ontology.Project))
            try:#add history
                projectHistory = proj['ownerHistory']['ref']
                self.g.add((self.resource[projectHistory], RDF.type, self.ontology.History))
                self.g.add((self.resource[projectID], self.ontology.hasHistory, self.resource[projectHistory]))
            except Exception:
                pass
            try:  # name is not always there
                projName = proj['name']
                self.g.add((self.resource[projectID], self.ontology.name, Literal(projName)))
            except Exception:
                pass
            try:  # description is not always there
                projDescription = proj['description']
                self.g.add((self.resource[projectID], self.ontology.description, Literal(projDescription)))
            except Exception:
                pass
            try:  # description is not always there
                projLongName = proj['longName']
                self.g.add((self.resource[projectID], self.ontology.longName, Literal(projLongName)))
            except Exception:
                pass
            try:  # description is not always there
                projPhase = proj['phase']
                self.g.add((self.resource[projectID], self.ontology.phase, Literal(projPhase)))
            except Exception:
                pass
            try:  # representationContexts is not always there
                for representationContexts in proj['representationContexts']:
                    context = representationContexts['ref']
                    self.g.add((self.resource[context], RDF.type, self.ontology.Context))
                    self.g.add((self.resource[projectID], self.ontology.hasRepresentationContext, self.resource[context]))
            except Exception:
                pass
            try:  # definedby is not always there
                for defined in proj['isDefinedBy']:
                    issdefined = defined['ref']
                    self.g.add((self.resource[issdefined], RDF.type, self.ontology.PropertySet))
                    self.g.add((self.resource[projectID], self.ontology.isDefinedBy, self.resource[issdefined]))
            except Exception:
                pass
            try:  # decompose is not always there
                for representation in proj['isDecomposedBy']:
                    rep = representation['ref']
                    self.g.add((self.resource["building_" + projectID], RDF.type, self.ontology.Object))
                    self.g.add((self.resource[rep], self.ontology.isDecomposedBy, self.resource["building_" + projectID]))
            except Exception:
                pass
            try:  # decompose is not always there
                for representation in proj['declares']:
                    rep = representation['ref']
                    self.g.add((self.resource["declaration_" + projectID], RDF.type, self.ontology.RelationDeclaration))
                    self.g.add((self.resource[rep], self.ontology.declares, self.resource["declaration_" + projectID]))
            except Exception:
                pass
            try:
                count, countElement = 1, 1
                for unit in proj['unitsInContext']['units']:
                    unitType = unit['type']
                    print(unitType)
                    if unitType == "IfcSIUnit":
                        self.g.add((self.resource["ifcUnit_" + projectID + "_" + str(count)], RDF.type, self.ontology.IfcSIUnit))
                        self.g.add((self.resource[projectID], self.ontology.hasUnit, self.resource["ifcUnit_" + projectID + "_" + str(count)]))
                        self.g.add((self.resource["ifcUnit_" + projectID + "_" + str(count)], self.ontology.unitType, Literal(unit['unitType'])))
                        self.g.add((self.resource["ifcUnit_" + projectID + "_" + str(count)], self.ontology.name, Literal(unit['name'])))
                        self.g.add((self.resource["ifcUnit_" + projectID + "_" + str(count)], self.ontology.dimensionType, Literal(unit['dimensions']['type'])))
                        if 'prefix' in list(unit.keys()):
                            self.g.add((self.resource["ifcUnit_" + projectID + "_" + str(count)], self.ontology.prefix, Literal(unit['prefix'])))
                        if 'LengthExponent' in list(unit['dimensions'].keys()):
                            self.g.add((self.resource["ifcUnit_" + projectID + "_" + str(count)], self.ontology.LengthExponent, Literal(unit['dimensions']['LengthExponent'])))
                        if 'TimeExponent' in list(unit['dimensions'].keys()):
                            self.g.add((self.resource["ifcUnit_" + projectID + "_" + str(count)], self.ontology.TimeExponent, Literal(unit['dimensions']['TimeExponent'])))
                        if 'ThermodynamicTemperatureExponent' in list(unit['dimensions'].keys()):
                            self.g.add((self.resource["ifcUnit_" + projectID + "_" + str(count)], self.ontology.ThermodynamicTemperatureExponent, Literal(unit['dimensions']['ThermodynamicTemperatureExponent'])))
                        if 'MassExponent' in list(unit['dimensions'].keys()):
                            self.g.add((self.resource["ifcUnit_" + projectID + "_" + str(count)], self.ontology.MassExponent, Literal(unit['dimensions']['MassExponent'])))
                        if 'ElectricCurrentExponent' in list(unit['dimensions'].keys()):
                            self.g.add((self.resource["ifcUnit_" + projectID + "_" + str(count)], self.ontology.ElectricCurrentExponent, Literal(unit['dimensions']['ElectricCurrentExponent'])))
                        if 'LuminousIntensityExponent' in list(unit['dimensions'].keys()):
                            self.g.add((self.resource["ifcUnit_" + projectID + "_" + str(count)], self.ontology.LuminousIntensityExponent, Literal(unit['dimensions']['LuminousIntensityExponent'])))
                    elif unitType == "IfcConversionBasedUnit":
                        self.g.add((self.resource["conversionBasedUnit_" + projectID + "_" + str(count)], RDF.type, self.ontology.ConversionBasedUnit))
                        self.g.add((self.resource[projectID], self.ontology.hasUnit, self.resource["conversionBasedUnit_" + projectID + "_" + str(count)]))
                        self.g.add((self.resource["conversionBasedUnit_" + projectID + "_" + str(count)], self.ontology.unitType, Literal(unit['unitType'])))
                        self.g.add((self.resource["conversionBasedUnit_" + projectID + "_" + str(count)], self.ontology.name, Literal(unit['name'])))
                        self.g.add((self.resource["conversionBasedUnit_" + projectID + "_" + str(count)], self.ontology.coversionType, Literal(unit['conversionFactor']['valueComponent']['type'])))
                        self.g.add((self.resource["conversionBasedUnit_" + projectID + "_" + str(count)], self.ontology.coversionValue, Literal(unit['conversionFactor']['valueComponent']['value'])))
                        self.g.add((self.resource["conversionBasedUnit_" + projectID + "_" + str(count)], self.ontology.componentType, Literal(unit['conversionFactor']['unitComponent']['unitType'])))
                        self.g.add((self.resource["conversionBasedUnit_" + projectID + "_" + str(count)], self.ontology.componentName, Literal(unit['conversionFactor']['unitComponent']['name'])))
                        self.g.add((self.resource["conversionBasedUnit_" + projectID + "_" + str(count)], self.ontology.dimensionType, Literal(unit['conversionFactor']['unitComponent']['dimensions']['type'])))
                        self.g.add((self.resource["conversionBasedUnit_" + projectID + "_" + str(count)], self.ontology.LengthExponent, Literal(unit['dimensions']['lengthExponent'])))
                        self.g.add((self.resource["conversionBasedUnit_" + projectID + "_" + str(count)], self.ontology.MassExponent, Literal(unit['dimensions']['massExponent'])))
                        self.g.add((self.resource["conversionBasedUnit_" + projectID + "_" + str(count)], self.ontology.TimeExponent, Literal(unit['dimensions']['timeExponent'])))
                        self.g.add((self.resource["conversionBasedUnit_" + projectID + "_" + str(count)], self.ontology.ElectricCurrentExponent, Literal(unit['dimensions']['electricCurrentExponent'])))
                        self.g.add((self.resource["conversionBasedUnit_" + projectID + "_" + str(count)], self.ontology.ThermodynamicTemperatureExponent, Literal(unit['dimensions']['thermodynamicTemperatureExponent'])))
                        self.g.add((self.resource["conversionBasedUnit_" + projectID + "_" + str(count)], self.ontology.AmountOfSubstanceExponent, Literal(unit['dimensions']['amountOfSubstanceExponent'])))
                        self.g.add((self.resource["conversionBasedUnit_" + projectID + "_" + str(count)], self.ontology.LuminousIntensityExponent, Literal(unit['dimensions']['luminousIntensityExponent'])))
                    elif unitType == "IfcDerivedUnit":
                        self.g.add((self.resource["derivedUnit_" + projectID + "_" + str(count)], RDF.type, self.ontology.DerivedUnit))
                        self.g.add((self.resource[projectID], self.ontology.hasUnit, self.resource["derivedUnit_" + projectID + "_" + str(count)]))
                        self.g.add((self.resource["derivedUnit_" + projectID + "_" + str(count)], self.ontology.unitType, Literal(unit['unitType'])))
                        for element in unit['elements']:

                            self.g.add((self.resource["derivedUnitElement_" + projectID + "_" + str(countElement)], RDF.type, self.ontology.DerivedUnit))
                            self.g.add((self.resource["derivedUnit_" + projectID + "_" + str(count)], self.ontology.hasElement, self.resource["derivedUnitElement_" + projectID + "_" + str(countElement)]))
                            self.g.add((self.resource["derivedUnitElement_" + projectID + "_" + str(countElement)], self.ontology.type, Literal(element['unit']['unitType'])))
                            try:
                                self.g.add((self.resource["derivedUnitElement_" + projectID + "_" + str(countElement)],
                                            self.ontology.prefix, Literal(element['prefix'])))
                            except Exception:
                                pass
                            try:
                                self.g.add((self.resource["derivedUnitElement_" + projectID + "_" + str(countElement)], self.ontology.name, Literal(element['unit']['name'])))
                            except Exception:
                                pass
                            self.g.add((self.resource["derivedUnitElement_" + projectID + "_" + str(countElement)], self.ontology.exponent, Literal(element['exponent'])))
                            self.g.add((self.resource["derivedUnitElement_" + projectID + "_" + str(countElement)], self.ontology.dimensionType, Literal(element['unit']['dimensions']['type'])))
                            for k in list(element['unit']['dimensions'].keys()):
                                if str(k) != "type":
                                     self.g.add((self.resource["derivedUnitElement_" + projectID + "_" + str(countElement)], self.ontology[k], Literal(element['unit']['dimensions'][k])))
                            countElement += 1
                    else:
                        pass
                    count += 1
            except Exception:
                pass

        # Create RDF triples
        # Serialize and save the RDF graph to a TTL file
        file_path = "output.ttl"
        self.g.serialize(destination=file_path, format="turtle")