{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://orthodox-ronl.github.io/VSA-tooling/schemas/vsa-template.schema.json",
  "title": "VSA template (draft-v0)",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "spec_version",
    "id",
    "genre",
    "tone",
    "do",
    "mode"
  ],
  "properties": {
    "spec_version": {
      "type": "string",
      "const": "draft-v0"
    },
    "id": {
      "type": "string",
      "pattern": "^[a-z0-9_-]+$"
    },
    "genre": {
      "type": "string",
      "enum": ["tropaar", "stichier", "vers", "other"]
    },
    "tone": {
      "type": "integer",
      "minimum": 1,
      "maximum": 8
    },
    "do": {
      "type": "string",
      "pattern": "^[A-G](#|b)?[0-9]$"
    },
    "mode": {
      "type": "string",
      "enum": ["major", "minor"]
    },
    "duration-model": {
      "type": "string",
      "minLength": 1
    },
    "pitches_status": {
      "type": "string",
      "enum": ["verified", "provisional"]
    },
    "source": {
      "type": "string",
      "minLength": 1
    },
    "key_signature": {
      "type": "object",
      "description": "Optional non-normative sheet hint; pitch truth is do+mode.",
      "additionalProperties": false,
      "properties": {
        "flats": { "type": "integer", "minimum": 0, "maximum": 7 },
        "sharps": { "type": "integer", "minimum": 0, "maximum": 7 }
      }
    },
    "same_as": {
      "type": "string",
      "pattern": "^[a-z0-9_-]+$"
    },
    "also_used_as": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "string",
        "enum": ["tropaar", "stichier", "vers", "other"]
      }
    },
    "cycle": {
      "type": "array",
      "minItems": 1,
      "items": { "type": "string", "minLength": 1 }
    },
    "final": {
      "type": "string",
      "minLength": 1
    },
    "sequence": {
      "type": "array",
      "minItems": 1,
      "items": { "type": "string", "minLength": 1 }
    },
    "text_mapping": {
      "type": "array",
      "minItems": 1,
      "items": { "$ref": "#/$defs/mapping_step" }
    },
    "mapping_plans": {
      "type": "array",
      "minItems": 1,
      "items": { "$ref": "#/$defs/mapping_plan" }
    },
    "default_mapping_plan": {
      "type": "string",
      "minLength": 1
    },
    "phrases": {
      "type": "array",
      "minItems": 1,
      "items": { "$ref": "#/$defs/phrase" }
    }
  },
  "oneOf": [
    {
      "required": ["same_as"],
      "not": {
        "anyOf": [
          { "required": ["cycle"] },
          { "required": ["final"] },
          { "required": ["sequence"] },
          { "required": ["phrases"] }
        ]
      }
    },
    {
      "required": ["cycle", "final", "phrases"],
      "not": { "required": ["sequence"] }
    },
    {
      "required": ["sequence", "phrases"],
      "not": {
        "anyOf": [
          { "required": ["cycle"] },
          { "required": ["final"] }
        ]
      }
    }
  ],
  "$defs": {
    "degree": {
      "type": "string",
      "pattern": "^(#|b)?(do|re|mi|fa|sol|la|ti)([+-][1-3])?$"
    },
    "pitches": {
      "type": "object",
      "additionalProperties": false,
      "required": ["S", "A", "T", "B"],
      "properties": {
        "S": { "$ref": "#/$defs/degree" },
        "A": { "$ref": "#/$defs/degree" },
        "T": { "$ref": "#/$defs/degree" },
        "B": { "$ref": "#/$defs/degree" }
      }
    },
    "event": {
      "type": "object",
      "additionalProperties": false,
      "required": ["role", "duration", "pitches"],
      "properties": {
        "role": {
          "type": "string",
          "enum": ["open", "recite", "cadence", "link"]
        },
        "duration": {
          "type": "string",
          "enum": ["~", "-", "-.", "~.", "_", "_.", "__", ".", ".."]
        },
        "optional": { "type": "boolean" },
        "anchor": {
          "type": "string",
          "enum": ["e.st.", "l.st.", "vl.st.", "l.lgr."]
        },
        "pitches": { "$ref": "#/$defs/pitches" }
      }
    },
    "of_group": {
      "type": "object",
      "additionalProperties": false,
      "required": ["of"],
      "properties": {
        "of": {
          "type": "array",
          "minItems": 2,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["events"],
            "properties": {
              "id": { "type": "string", "minLength": 1 },
              "events": {
                "type": "array",
                "minItems": 1,
                "items": { "$ref": "#/$defs/event" }
              }
            }
          }
        }
      }
    },
    "phrase": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "events"],
      "properties": {
        "id": { "type": "string", "minLength": 1 },
        "events": {
          "type": "array",
          "minItems": 1,
          "items": {
            "oneOf": [
              { "$ref": "#/$defs/event" },
              { "$ref": "#/$defs/of_group" }
            ]
          }
        }
      }
    },
    "mapping_step": {
      "oneOf": [
        {
          "type": "object",
          "additionalProperties": false,
          "required": ["phrase"],
          "properties": {
            "phrase": { "type": "string", "minLength": 1 }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": ["sequence"],
          "properties": {
            "sequence": {
              "type": "array",
              "minItems": 1,
              "items": { "type": "string", "minLength": 1 }
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": ["repeat"],
          "properties": {
            "repeat": {
              "type": "array",
              "minItems": 1,
              "items": { "type": "string", "minLength": 1 }
            },
            "until": {}
          }
        }
      ]
    },
    "mapping_plan": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "steps"],
      "properties": {
        "id": { "type": "string", "minLength": 1 },
        "label": { "type": "string", "minLength": 1 },
        "when": { "type": "object" },
        "steps": {
          "type": "array",
          "minItems": 1,
          "items": { "$ref": "#/$defs/mapping_step" }
        }
      }
    }
  }
}
