from . import schema_org

CONTEXTS = [
    {
        "shortId": "LDP",
        "contextUrl": None,
        "documentUrl": "http://www.w3.org/ns/ldp",
        "document": {
            "@context": {
                "ldp": "http://www.w3.org/ns/ldp#",
                "id": "@id",
                "type": "@type",
                "Container": "ldp:Container",
                "BasicContainer": "ldp:BasicContainer",
                "DirectContainer": "ldp:DirectContainer",
                "IndirectContainer": "ldp:IndirectContainer",
                "hasMemberRelation": {"@id": "ldp:hasMemberRelation", "@type": "@id"},
                "isMemberOfRelation": {"@id": "ldp:isMemberOfRelation", "@type": "@id"},
                "membershipResource": {"@id": "ldp:membershipResource", "@type": "@id"},
                "insertedContentRelation": {
                    "@id": "ldp:insertedContentRelation",
                    "@type": "@id",
                },
                "contains": {"@id": "ldp:contains", "@type": "@id"},
                "member": {"@id": "ldp:member", "@type": "@id"},
                "constrainedBy": {"@id": "ldp:constrainedBy", "@type": "@id"},
                "Resource": "ldp:Resource",
                "RDFSource": "ldp:RDFSource",
                "NonRDFSource": "ldp:NonRDFSource",
                "MemberSubject": "ldp:MemberSubject",
                "PreferContainment": "ldp:PreferContainment",
                "PreferMembership": "ldp:PreferMembership",
                "PreferMinimalContainer": "ldp:PreferMinimalContainer",
                "PageSortCriterion": "ldp:PageSortCriterion",
                "pageSortCriteria": {
                    "@id": "ldp:pageSortCriteria",
                    "@type": "@id",
                    "@container": "@list",
                },
                "pageSortPredicate": {"@id": "ldp:pageSortPredicate", "@type": "@id"},
                "pageSortOrder": {"@id": "ldp:pageSortOrder", "@type": "@id"},
                "pageSortCollation": {"@id": "ldp:pageSortCollation", "@type": "@id"},
                "Ascending": "ldp:Ascending",
                "Descending": "ldp:Descending",
                "Page": "ldp:Page",
                "pageSequence": {"@id": "ldp:pageSequence", "@type": "@id"},
                "inbox": {"@id": "ldp:inbox", "@type": "@id"},
            }
        },
    },
    {
        "shortId": "AS",
        "contextUrl": None,
        "documentUrl": "https://www.w3.org/ns/activitystreams",
        "document": {
            "@context": {
                "@vocab": "_:",
                "xsd": "http://www.w3.org/2001/XMLSchema#",
                "as": "https://www.w3.org/ns/activitystreams#",
                "ldp": "http://www.w3.org/ns/ldp#",
                "id": "@id",
                "type": "@type",
                "Accept": "as:Accept",
                "Activity": "as:Activity",
                "IntransitiveActivity": "as:IntransitiveActivity",
                "Add": "as:Add",
                "Announce": "as:Announce",
                "Application": "as:Application",
                "Arrive": "as:Arrive",
                "Article": "as:Article",
                "Audio": "as:Audio",
                "Block": "as:Block",
                "Collection": "as:Collection",
                "CollectionPage": "as:CollectionPage",
                "Relationship": "as:Relationship",
                "Create": "as:Create",
                "Delete": "as:Delete",
                "Dislike": "as:Dislike",
                "Document": "as:Document",
                "Event": "as:Event",
                "Follow": "as:Follow",
                "Flag": "as:Flag",
                "Group": "as:Group",
                "Ignore": "as:Ignore",
                "Image": "as:Image",
                "Invite": "as:Invite",
                "Join": "as:Join",
                "Leave": "as:Leave",
                "Like": "as:Like",
                "Link": "as:Link",
                "Mention": "as:Mention",
                "Note": "as:Note",
                "Object": "as:Object",
                "Offer": "as:Offer",
                "OrderedCollection": "as:OrderedCollection",
                "OrderedCollectionPage": "as:OrderedCollectionPage",
                "Organization": "as:Organization",
                "Page": "as:Page",
                "Person": "as:Person",
                "Place": "as:Place",
                "Profile": "as:Profile",
                "Question": "as:Question",
                "Reject": "as:Reject",
                "Remove": "as:Remove",
                "Service": "as:Service",
                "TentativeAccept": "as:TentativeAccept",
                "TentativeReject": "as:TentativeReject",
                "Tombstone": "as:Tombstone",
                "Undo": "as:Undo",
                "Update": "as:Update",
                "Video": "as:Video",
                "View": "as:View",
                "Listen": "as:Listen",
                "Read": "as:Read",
                "Move": "as:Move",
                "Travel": "as:Travel",
                "IsFollowing": "as:IsFollowing",
                "IsFollowedBy": "as:IsFollowedBy",
                "IsContact": "as:IsContact",
                "IsMember": "as:IsMember",
                "subject": {"@id": "as:subject", "@type": "@id"},
                "relationship": {"@id": "as:relationship", "@type": "@id"},
                "actor": {"@id": "as:actor", "@type": "@id"},
                "attributedTo": {"@id": "as:attributedTo", "@type": "@id"},
                "attachment": {"@id": "as:attachment", "@type": "@id"},
                "bcc": {"@id": "as:bcc", "@type": "@id"},
                "bto": {"@id": "as:bto", "@type": "@id"},
                "cc": {"@id": "as:cc", "@type": "@id"},
                "context": {"@id": "as:context", "@type": "@id"},
                "current": {"@id": "as:current", "@type": "@id"},
                "first": {"@id": "as:first", "@type": "@id"},
                "generator": {"@id": "as:generator", "@type": "@id"},
                "icon": {"@id": "as:icon", "@type": "@id"},
                "image": {"@id": "as:image", "@type": "@id"},
                "inReplyTo": {"@id": "as:inReplyTo", "@type": "@id"},
                "items": {"@id": "as:items", "@type": "@id"},
                "instrument": {"@id": "as:instrument", "@type": "@id"},
                "orderedItems": {
                    "@id": "as:items",
                    "@type": "@id",
                    "@container": "@list",
                },
                "last": {"@id": "as:last", "@type": "@id"},
                "location": {"@id": "as:location", "@type": "@id"},
                "next": {"@id": "as:next", "@type": "@id"},
                "object": {"@id": "as:object", "@type": "@id"},
                "oneOf": {"@id": "as:oneOf", "@type": "@id"},
                "anyOf": {"@id": "as:anyOf", "@type": "@id"},
                "closed": {"@id": "as:closed", "@type": "xsd:dateTime"},
                "origin": {"@id": "as:origin", "@type": "@id"},
                "accuracy": {"@id": "as:accuracy", "@type": "xsd:float"},
                "prev": {"@id": "as:prev", "@type": "@id"},
                "preview": {"@id": "as:preview", "@type": "@id"},
                "replies": {"@id": "as:replies", "@type": "@id"},
                "result": {"@id": "as:result", "@type": "@id"},
                "audience": {"@id": "as:audience", "@type": "@id"},
                "partOf": {"@id": "as:partOf", "@type": "@id"},
                "tag": {"@id": "as:tag", "@type": "@id"},
                "target": {"@id": "as:target", "@type": "@id"},
                "to": {"@id": "as:to", "@type": "@id"},
                "url": {"@id": "as:url", "@type": "@id"},
                "altitude": {"@id": "as:altitude", "@type": "xsd:float"},
                "content": "as:content",
                "contentMap": {"@id": "as:content", "@container": "@language"},
                "name": "as:name",
                "nameMap": {"@id": "as:name", "@container": "@language"},
                "duration": {"@id": "as:duration", "@type": "xsd:duration"},
                "endTime": {"@id": "as:endTime", "@type": "xsd:dateTime"},
                "height": {"@id": "as:height", "@type": "xsd:nonNegativeInteger"},
                "href": {"@id": "as:href", "@type": "@id"},
                "hreflang": "as:hreflang",
                "latitude": {"@id": "as:latitude", "@type": "xsd:float"},
                "longitude": {"@id": "as:longitude", "@type": "xsd:float"},
                "mediaType": "as:mediaType",
                "published": {"@id": "as:published", "@type": "xsd:dateTime"},
                "radius": {"@id": "as:radius", "@type": "xsd:float"},
                "rel": "as:rel",
                "startIndex": {
                    "@id": "as:startIndex",
                    "@type": "xsd:nonNegativeInteger",
                },
                "startTime": {"@id": "as:startTime", "@type": "xsd:dateTime"},
                "summary": "as:summary",
                "summaryMap": {"@id": "as:summary", "@container": "@language"},
                "totalItems": {
                    "@id": "as:totalItems",
                    "@type": "xsd:nonNegativeInteger",
                },
                "units": "as:units",
                "updated": {"@id": "as:updated", "@type": "xsd:dateTime"},
                "width": {"@id": "as:width", "@type": "xsd:nonNegativeInteger"},
                "describes": {"@id": "as:describes", "@type": "@id"},
                "formerType": {"@id": "as:formerType", "@type": "@id"},
                "deleted": {"@id": "as:deleted", "@type": "xsd:dateTime"},
                "inbox": {"@id": "ldp:inbox", "@type": "@id"},
                "outbox": {"@id": "as:outbox", "@type": "@id"},
                "following": {"@id": "as:following", "@type": "@id"},
                "followers": {"@id": "as:followers", "@type": "@id"},
                "streams": {"@id": "as:streams", "@type": "@id"},
                "preferredUsername": "as:preferredUsername",
                "endpoints": {"@id": "as:endpoints", "@type": "@id"},
                "uploadMedia": {"@id": "as:uploadMedia", "@type": "@id"},
                "proxyUrl": {"@id": "as:proxyUrl", "@type": "@id"},
                "liked": {"@id": "as:liked", "@type": "@id"},
                "oauthAuthorizationEndpoint": {
                    "@id": "as:oauthAuthorizationEndpoint",
                    "@type": "@id",
                },
                "oauthTokenEndpoint": {"@id": "as:oauthTokenEndpoint", "@type": "@id"},
                "provideClientKey": {"@id": "as:provideClientKey", "@type": "@id"},
                "signClientKey": {"@id": "as:signClientKey", "@type": "@id"},
                "sharedInbox": {"@id": "as:sharedInbox", "@type": "@id"},
                "Public": {"@id": "as:Public", "@type": "@id"},
                "source": "as:source",
                "likes": {"@id": "as:likes", "@type": "@id"},
                "shares": {"@id": "as:shares", "@type": "@id"},
                # Added manually
                "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
                "Hashtag": "as:Hashtag",
            }
        },
    },
    {
        "shortId": "SC",
        "contextUrl": None,
        "documentUrl": "http://schema.org",
        "document": {"@context": schema_org.CONTEXT},
    },
    {
        "shortId": "SEC",
        "contextUrl": None,
        "documentUrl": "https://w3id.org/security/v1",
        "document": {
            "@context": {
                "id": "@id",
                "type": "@type",
                "dc": "http://purl.org/dc/terms/",
                "sec": "https://w3id.org/security#",
                "xsd": "http://www.w3.org/2001/XMLSchema#",
                "EcdsaKoblitzSignature2016": "sec:EcdsaKoblitzSignature2016",
                "Ed25519Signature2018": "sec:Ed25519Signature2018",
                "EncryptedMessage": "sec:EncryptedMessage",
                "GraphSignature2012": "sec:GraphSignature2012",
                "LinkedDataSignature2015": "sec:LinkedDataSignature2015",
                "LinkedDataSignature2016": "sec:LinkedDataSignature2016",
                "CryptographicKey": "sec:Key",
                "authenticationTag": "sec:authenticationTag",
                "canonicalizationAlgorithm": "sec:canonicalizationAlgorithm",
                "cipherAlgorithm": "sec:cipherAlgorithm",
                "cipherData": "sec:cipherData",
                "cipherKey": "sec:cipherKey",
                "created": {"@id": "dc:created", "@type": "xsd:dateTime"},
                "creator": {"@id": "dc:creator", "@type": "@id"},
                "digestAlgorithm": "sec:digestAlgorithm",
                "digestValue": "sec:digestValue",
                "domain": "sec:domain",
                "encryptionKey": "sec:encryptionKey",
                "expiration": {"@id": "sec:expiration", "@type": "xsd:dateTime"},
                "expires": {"@id": "sec:expiration", "@type": "xsd:dateTime"},
                "initializationVector": "sec:initializationVector",
                "iterationCount": "sec:iterationCount",
                "nonce": "sec:nonce",
                "normalizationAlgorithm": "sec:normalizationAlgorithm",
                "owner": {"@id": "sec:owner", "@type": "@id"},
                "password": "sec:password",
                "privateKey": {"@id": "sec:privateKey", "@type": "@id"},
                "privateKeyPem": "sec:privateKeyPem",
                "publicKey": {"@id": "sec:publicKey", "@type": "@id"},
                "publicKeyBase58": "sec:publicKeyBase58",
                "publicKeyPem": "sec:publicKeyPem",
                "publicKeyWif": "sec:publicKeyWif",
                "publicKeyService": {"@id": "sec:publicKeyService", "@type": "@id"},
                "revoked": {"@id": "sec:revoked", "@type": "xsd:dateTime"},
                "salt": "sec:salt",
                "signature": "sec:signature",
                "signatureAlgorithm": "sec:signingAlgorithm",
                "signatureValue": "sec:signatureValue",
            }
        },
    },
    {
        "shortId": "FW",
        "contextUrl": None,
        "documentUrl": "https://funkwhale.audio/ns",
        "document": {
            "@context": {
                "id": "@id",
                "type": "@type",
                "as": "https://www.w3.org/ns/activitystreams#",
                "fw": "https://funkwhale.audio/ns#",
                "schema": "http://schema.org#",
                "xsd": "http://www.w3.org/2001/XMLSchema#",
                "Album": "fw:Album",
                "Track": "fw:Track",
                "Artist": "fw:Artist",
                "ArtistCredit": "fw:ArtistCredit",
                "Library": "fw:Library",
                "Playlist": "fw:Playlist",
                "PlaylistTrack": "fw:PlaylistTrack",
                "bitrate": {"@id": "fw:bitrate", "@type": "xsd:nonNegativeInteger"},
                "size": {"@id": "fw:size", "@type": "xsd:nonNegativeInteger"},
                "position": {"@id": "fw:position", "@type": "xsd:nonNegativeInteger"},
                "disc": {"@id": "fw:disc", "@type": "xsd:nonNegativeInteger"},
                "library": {"@id": "fw:library", "@type": "@id"},
                "track": {"@id": "fw:track", "@type": "@id"},
                "cover": {"@id": "fw:cover", "@type": "as:Link"},
                "album": {"@id": "fw:album", "@type": "@id"},
                "artist": {"@id": "fw:artist", "@type": "@id"},
                "artists": {"@id": "fw:artists", "@type": "@id", "@container": "@list"},
                "artist_credit": {
                    "@id": "fw:artist_credit",
                    "@type": "@id",
                    "@container": "@list",
                },
                "joinphrase": {"@id": "fw:joinphrase", "@type": "xsd:string"},
                "credit": {"@id": "fw:credit", "@type": "xsd:string"},
                "index": {"@id": "fw:index", "@type": "xsd:nonNegativeInteger"},
                "released": {"@id": "fw:released", "@type": "xsd:date"},
                "musicbrainzId": "fw:musicbrainzId",
                "license": {"@id": "fw:license", "@type": "@id"},
                "copyright": "fw:copyright",
                "category": "schema:category",
                "language": "schema:inLanguage",
                "playlist": {"@id": "fw:playlist", "@type": "@id"},
            }
        },
    },
    {
        "shortId": "LITEPUB",
        "contextUrl": None,
        "documentUrl": "http://litepub.social/ns",
        # from https://git.pleroma.social/pleroma/pleroma/-/blob/release/2.2.3/priv/static/schemas/litepub-0.1.jsonld
        "document": {
            "@context": {
                "Emoji": "toot:Emoji",
                "Hashtag": "as:Hashtag",
                "PropertyValue": "schema:PropertyValue",
                "atomUri": "ostatus:atomUri",
                "conversation": {"@id": "ostatus:conversation", "@type": "@id"},
                "discoverable": "toot:discoverable",
                "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
                "capabilities": "litepub:capabilities",
                "ostatus": "http://ostatus.org#",
                "schema": "http://schema.org#",
                "toot": "http://joinmastodon.org/ns#",
                "value": "schema:value",
                "sensitive": "as:sensitive",
                "litepub": "http://litepub.social/ns#",
                "invisible": "litepub:invisible",
                "directMessage": "litepub:directMessage",
                "listMessage": {"@id": "litepub:listMessage", "@type": "@id"},
                "oauthRegistrationEndpoint": {
                    "@id": "litepub:oauthRegistrationEndpoint",
                    "@type": "@id",
                },
                "EmojiReact": "litepub:EmojiReact",
                "ChatMessage": "litepub:ChatMessage",
                "alsoKnownAs": {"@id": "as:alsoKnownAs", "@type": "@id"},
            }
        },
    },
]

CONTEXTS_BY_ID = {c["shortId"]: c for c in CONTEXTS}


class NS:
    def __init__(self, conf):
        self.conf = conf
        self.baseUrl = self.conf["document"]["@context"][self.conf["shortId"].lower()]

    def __repr__(self):
        return "<{}: {}>".format(self.conf["shortId"], self.baseUrl)

    def __getattr__(self, key):
        if key not in self.conf["document"]["@context"]:
            raise AttributeError(
                f"{key} is not a valid property of context {self.baseUrl}"
            )
        return self.baseUrl + key


class NoopContext:
    def __getattr__(self, key):
        return f"_:{key}"


NOOP = NoopContext()
AS = NS(CONTEXTS_BY_ID["AS"])
LDP = NS(CONTEXTS_BY_ID["LDP"])
SEC = NS(CONTEXTS_BY_ID["SEC"])
FW = NS(CONTEXTS_BY_ID["FW"])
SC = NS(CONTEXTS_BY_ID["SC"])
LITEPUB = NS(CONTEXTS_BY_ID["LITEPUB"])
