{
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "$id": "https://omeka-s-contrib.github.io/omeka-s-blueprints/schema/v0/blueprint-schema.json",
    "title": "Omeka S Blueprint",
    "description": "Declarative description of an Omeka S environment.",
    "type": "object",
    "additionalProperties": false,
    "properties": {
        "$schema": { "type": "string" },
        "meta": {
            "type": "object",
            "description": "Human-readable metadata.",
            "additionalProperties": false,
            "properties": {
                "title": { "type": "string" },
                "author": { "type": "string" },
                "description": { "type": "string" }
            }
        },
        "preferredVersions": {
            "type": "object",
            "description": "Informational runtime targets.",
            "additionalProperties": false,
            "properties": {
                "php": { "type": "string" },
                "omeka": { "type": "string" }
            }
        },
        "install": {
            "type": "object",
            "description": "Values used when installing Omeka S. Consumers that work on an existing installation ignore them.",
            "additionalProperties": false,
            "properties": {
                "title": { "type": "string" },
                "locale": { "type": "string" },
                "timezone": { "type": "string" },
                "admin": {
                    "type": "object",
                    "description": "First global administrator. Consumers may take the password from their own input (flags, environment) or generate it.",
                    "additionalProperties": false,
                    "required": ["email"],
                    "properties": {
                        "name": { "type": "string" },
                        "email": { "type": "string", "format": "email" },
                        "password": { "type": "string", "minLength": 1 }
                    }
                }
            }
        },
        "modules": { "$ref": "#/$defs/moduleList" },
        "themes": { "$ref": "#/$defs/themeList" },
        "files": { "$ref": "#/$defs/fileList" },
        "vocabularies": { "$ref": "#/$defs/vocabularyList" },
        "resourceTemplates": { "$ref": "#/$defs/resourceTemplateList" },
        "settings": { "$ref": "#/$defs/settings" },
        "users": { "$ref": "#/$defs/userList" },
        "itemSets": { "$ref": "#/$defs/itemSetList" },
        "items": { "$ref": "#/$defs/itemList" },
        "sites": { "type": "array", "items": { "$ref": "#/$defs/site" } }
    },
    "patternProperties": {
        "^x-": {
            "description": "Implementation-specific extension (e.g. x-playground, x-omeka-s-cli). Its content is defined by that implementation; other consumers ignore it."
        }
    },

    "$defs": {
        "reference": {
            "type": "object",
            "description": "A pointer to an external file or URL whose contents are spliced into the enclosing list. The referenced document is itself a valid list (or single item) for that key.",
            "additionalProperties": false,
            "required": ["$import"],
            "properties": {
                "$import": { "type": "string", "minLength": 1 }
            }
        },

        "moduleId": {
            "type": "string",
            "description": "Omeka S module identifier (equal to the module's directory name).",
            "pattern": "^[A-Za-z0-9][A-Za-z0-9_-]*$"
        },
        "addonSource": {
            "type": "string",
            "minLength": 1,
            "description": "Where to get the add-on: a ZIP release URL (https://…/Module-1.2.3.zip), a git repository URL, or a scheme-prefixed reference (gh:owner/repo). Consumers reject forms they do not support. Without a source, the add-on already present in the installation is used; otherwise 'name' is resolved through the omeka.org add-on API."
        },
        "addonVersion": {
            "type": "string",
            "description": "Release to use when resolving through omeka.org, or tag/branch for a git source. A source that pins a release (a ZIP URL) wins; consumers may warn when they differ."
        },
        "module": {
            "type": "object",
            "additionalProperties": false,
            "required": ["name"],
            "properties": {
                "name": { "$ref": "#/$defs/moduleId" },
                "state": {
                    "type": "string",
                    "description": "download = place files only; install = install; activate = install and enable.",
                    "enum": ["download", "install", "activate"]
                },
                "version": { "$ref": "#/$defs/addonVersion" },
                "source": { "$ref": "#/$defs/addonSource" }
            }
        },
        "moduleList": {
            "type": "array",
            "items": {
                "oneOf": [
                    { "$ref": "#/$defs/moduleId" },
                    { "$ref": "#/$defs/module" },
                    { "$ref": "#/$defs/reference" }
                ]
            }
        },

        "themeId": {
            "type": "string",
            "description": "Omeka S theme identifier (equal to the theme's directory name).",
            "pattern": "^[A-Za-z0-9][A-Za-z0-9_-]*$"
        },
        "theme": {
            "type": "object",
            "additionalProperties": false,
            "required": ["name"],
            "properties": {
                "name": { "$ref": "#/$defs/themeId" },
                "version": { "$ref": "#/$defs/addonVersion" },
                "source": { "$ref": "#/$defs/addonSource" }
            }
        },
        "themeList": {
            "type": "array",
            "items": {
                "oneOf": [
                    { "$ref": "#/$defs/themeId" },
                    { "$ref": "#/$defs/theme" },
                    { "$ref": "#/$defs/reference" }
                ]
            }
        },

        "file": {
            "type": "object",
            "description": "A file placed in the Omeka S installation (e.g. config/cleanurl.config.php), applied after modules and themes are in place.",
            "additionalProperties": false,
            "required": ["source", "destination"],
            "properties": {
                "source": {
                    "type": "string",
                    "format": "uri-reference",
                    "description": "Path or URL of the file. Relative paths resolve against the blueprint file."
                },
                "destination": {
                    "type": "string",
                    "description": "Path relative to the Omeka S root. Absolute paths and '..' segments are not allowed. With extract, the directory to extract into.",
                    "pattern": "^(?![/\\\\])(?![A-Za-z]:)(?!(?:.*[/\\\\])?\\.\\.(?:[/\\\\]|$)).+$"
                },
                "extract": {
                    "type": "boolean",
                    "default": false,
                    "description": "Treat source as a ZIP archive and extract it into destination. If the archive has a single top-level directory, its contents are extracted, as with add-on archives."
                }
            }
        },
        "fileList": {
            "type": "array",
            "items": {
                "oneOf": [
                    { "$ref": "#/$defs/file" },
                    { "$ref": "#/$defs/reference" }
                ]
            }
        },

        "vocabulary": {
            "type": "object",
            "description": "A vocabulary to import via the RDF importer.",
            "additionalProperties": false,
            "required": ["source", "namespaceUri", "prefix", "label"],
            "properties": {
                "source": {
                    "type": "string",
                    "format": "uri-reference",
                    "description": "Path or URL of the RDF file. Relative paths resolve against the blueprint file."
                },
                "namespaceUri": { "type": "string" },
                "prefix": { "type": "string" },
                "label": { "type": "string" },
                "comment": { "type": "string" },
                "format": { "type": "string" },
                "lang": { "type": "string" },
                "labelProperty": { "type": "string", "description": "RDF property to use for labels." },
                "commentProperty": { "type": "string", "description": "RDF property to use for comments." }
            }
        },
        "vocabularyList": {
            "type": "array",
            "items": {
                "oneOf": [
                    { "$ref": "#/$defs/vocabulary" },
                    { "$ref": "#/$defs/reference" }
                ]
            }
        },

        "resourceTemplate": {
            "type": "object",
            "additionalProperties": false,
            "required": ["source"],
            "properties": {
                "source": {
                    "type": "string",
                    "description": "Path or URL to a resource-template JSON export."
                },
                "label": { "type": "string" },
                "ignoreDeps": { "type": "boolean" }
            }
        },
        "resourceTemplateList": {
            "type": "array",
            "items": {
                "oneOf": [
                    { "$ref": "#/$defs/resourceTemplate" },
                    { "$ref": "#/$defs/reference" }
                ]
            }
        },

        "settingsMap": {
            "type": "object",
            "description": "A map of global setting id => value.",
            "additionalProperties": true
        },
        "settings": {
            "description": "Global settings. Either an inline map, or a list of maps/references merged in order.",
            "oneOf": [
                {
                    "allOf": [
                        { "$ref": "#/$defs/settingsMap" },
                        { "not": { "required": ["$import"] } }
                    ]
                },
                {
                    "type": "array",
                    "items": {
                        "oneOf": [
                            {
                                "allOf": [
                                    { "$ref": "#/$defs/settingsMap" },
                                    { "not": { "required": ["$import"] } }
                                ]
                            },
                            { "$ref": "#/$defs/reference" }
                        ]
                    }
                }
            ]
        },

        "user": {
            "type": "object",
            "additionalProperties": false,
            "required": ["email"],
            "properties": {
                "email": { "type": "string", "format": "email" },
                "username": { "type": "string" },
                "password": { "type": "string", "minLength": 1 },
                "role": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Omeka S role id. Core roles: global_admin, site_admin, editor, reviewer, author, researcher. Modules can register more (e.g. guest)."
                },
                "isActive": { "type": "boolean" },
                "settings": {
                    "type": "object",
                    "description": "Per-user settings written to user_setting (e.g. limit_to_granted_sites).",
                    "additionalProperties": true
                }
            }
        },
        "userList": {
            "type": "array",
            "items": {
                "oneOf": [
                    { "$ref": "#/$defs/user" },
                    { "$ref": "#/$defs/reference" }
                ]
            }
        },

        "itemSet": {
            "type": "object",
            "additionalProperties": false,
            "required": ["title"],
            "properties": {
                "title": { "type": "string" },
                "description": { "type": "string" }
            }
        },
        "itemSetList": {
            "type": "array",
            "items": {
                "oneOf": [
                    { "$ref": "#/$defs/itemSet" },
                    { "$ref": "#/$defs/reference" }
                ]
            }
        },

        "media": {
            "type": "object",
            "additionalProperties": false,
            "required": ["url"],
            "properties": {
                "type": { "type": "string", "enum": ["url"] },
                "url": { "type": "string", "format": "uri-reference" },
                "title": { "type": "string" },
                "altText": { "type": "string" }
            }
        },
        "item": {
            "type": "object",
            "additionalProperties": false,
            "required": ["title"],
            "properties": {
                "title": { "type": "string" },
                "description": { "type": "string" },
                "creator": { "type": "string" },
                "itemSets": { "type": "array", "items": { "type": "string" } },
                "sites": {
                    "type": "array",
                    "description": "Slugs (or titles) of the sites this item is assigned to. Defaults to the default site.",
                    "items": { "type": "string" }
                },
                "media": { "type": "array", "items": { "$ref": "#/$defs/media" } }
            }
        },
        "itemList": {
            "type": "array",
            "items": {
                "oneOf": [
                    { "$ref": "#/$defs/item" },
                    { "$ref": "#/$defs/reference" }
                ]
            }
        },

        "sitePermission": {
            "type": "object",
            "additionalProperties": false,
            "required": ["user"],
            "properties": {
                "user": { "type": "string", "description": "Email of an existing blueprint user." },
                "role": { "type": "string", "enum": ["viewer", "editor", "admin"] }
            }
        },
        "site": {
            "type": "object",
            "additionalProperties": false,
            "required": ["title"],
            "properties": {
                "title": { "type": "string" },
                "slug": { "type": "string" },
                "summary": { "type": "string" },
                "theme": { "$ref": "#/$defs/themeId" },
                "isPublic": { "type": "boolean" },
                "setAsDefault": { "type": "boolean" },
                "permissions": {
                    "type": "array",
                    "description": "Per-site user permissions, by user email.",
                    "items": { "$ref": "#/$defs/sitePermission" }
                }
            }
        }
    }
}