{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "$id": "https://www.minizinc.org/schemas/fznjson",
  "title": "FlatZincJSON",
  "description": "A JSON representation of a FlatZinc model",

  "$defs": {
    "identifier": { "type": "string", "pattern": "[A-Za-z][A-Za-z0-9_]*" },
    "literal": {
      "oneOf": [
        { "type": "number" },
        { "$ref": "#/$defs/identifier" },
        { "type": "boolean" },
        {
          "type": "object",
          "properties": {
            "set": {
              "type": "array",
              "items": {
                "type": "array",
                "items": [{ "type": "number" }, { "type": "number" }]
              }
            }
          },
          "required": ["set"]
        },
        {
          "type": "object",
          "properties": {
            "string": { "type": "string" }
          },
          "required": ["string"]
        }
      ]
    },
    "literals": { "type": "array", "items": { "$ref": "#/$defs/literal" } },
    "argument": {
      "oneOf": [{ "$ref": "#/$defs/literals" }, { "$ref": "#/$defs/literal" }]
    },
    "annotation": {
      "oneOf": [{ "$ref": "#/$defs/annotationCall" }, { "type": "string" }]
    },
    "annotations": {
      "type": "array",
      "items": { "$ref": "#/$defs/annotation" }
    },
    "annotationArgument": {
      "oneOf": [
        { "$ref": "#/$defs/annotationLiterals" },
        { "$ref": "#/$defs/annotationLiteral" }
      ]
    },
    "annotationCall": {
      "type": "object",
      "properties": {
        "id": { "$ref": "#/$defs/identifier" },
        "args": {
          "type": "array",
          "items": { "$ref": "#/$defs/annotationArgument" }
        }
      },
      "required": ["id", "args"]
    },
    "annotationLiterals": {
      "type": "array",
      "items": { "$ref": "#/$defs/annotationLiteral" }
    },
    "annotationLiteral": {
      "oneOf": [
        { "$ref": "#/$defs/literal" },
        { "$ref": "#/$defs/annotationCall" }
      ]
    },
    "domain": {
      "type": "array",
      "items": {
        "type": "array",
        "items": [{ "type": "number" }, { "type": "number" }]
      }
    }
  },

  "type": "object",
  "properties": {
    "version": { "type": "string" },
    "variables": {
      "type": "object",
      "patternProperties": {
        "[A-Za-z][A-Za-z0-9_]*": {
          "type": "object",
          "properties": {
            "type": {
              "enum": ["bool", "float", "int", "set of int"]
            },
            "domain": { "$ref": "#/$defs/domain" },
            "rhs": { "$ref": "#/$defs/literal" },
            "introduced": {
              "type": "boolean"
            },
            "defined": {
              "type": "boolean"
            },
            "ann": { "$ref": "#/$defs/annotations" }
          },
          "required": ["type"]
        }
      }
    },
    "arrays": {
      "type": "object",
      "patternProperties": {
        "[A-Za-z][A-Za-z0-9_]*": {
          "type": "object",
          "properties": {
            "a": {
              "type": "array",
              "items": { "$ref": "#/$defs/literal" }
            },
            "ann": { "$ref": "#/$defs/annotations" },
            "introduced": {
              "type": "boolean"
            },
            "defined": {
              "type": "boolean"
            }
          },
          "required": ["a"]
        }
      }
    },
    "constraints": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": { "$ref": "#/$defs/identifier" },
          "args": {
            "type": "array",
            "items": { "$ref": "#/$defs/argument" }
          },
          "ann": { "$ref": "#/$defs/annotations" },
          "defines": { "$ref": "#/$defs/identifier" }
        },
        "required": ["id", "args"]
      }
    },
    "output": {
      "type": "array",
      "items": { "$ref": "#/$defs/identifier" }
    },
    "solve": {
      "type": "object",
      "properties": {
        "method": {
          "enum": ["satisfy", "minimize", "maximize"]
        },
        "objective": { "$ref": "#/$defs/literal" },
        "ann": { "$ref": "#/$defs/annotations" }
      },
      "required": ["method"]
    }
  },
  "required": [
    "version",
    "variables",
    "arrays",
    "output",
    "constraints",
    "solve"
  ]
}
