{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://docs.troupes.ai/schema/0.12/message.schema.json",
  "title": "Troupe message",
  "description": "Every line after the first in a Troupe session file: a message.",
  "type": "object",
  "required": [
    "id",
    "from",
    "content"
  ],
  "additionalProperties": false,
  "properties": {
    "id": {
      "$ref": "bundle.schema.json#/$defs/opaqueId"
    },
    "parent": {
      "$ref": "bundle.schema.json#/$defs/opaqueId"
    },
    "opening": {
      "$ref": "bundle.schema.json#/$defs/id"
    },
    "from": {
      "enum": [
        "player",
        "model",
        "system"
      ]
    },
    "char": {
      "$ref": "bundle.schema.json#/$defs/characterId"
    },
    "content": {
      "type": "array",
      "items": {
        "$ref": "bundle.schema.json#/$defs/part"
      }
    },
    "at": {
      "$ref": "bundle.schema.json#/$defs/timestamp"
    },
    "changes": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/change"
      },
      "minItems": 1
    },
    "activated": {
      "description": "The entries that reached the model for this message, as distinct references (Format 12.4).",
      "type": "array",
      "uniqueItems": true,
      "items": {
        "$ref": "bundle.schema.json#/$defs/entryRef"
      },
      "minItems": 1
    },
    "entries": {
      "type": "array",
      "items": {
        "$ref": "bundle.schema.json#/$defs/entry"
      },
      "minItems": 1
    },
    "summary": {
      "type": "object",
      "required": [
        "text",
        "from"
      ],
      "additionalProperties": false,
      "properties": {
        "text": {
          "type": "string"
        },
        "from": {
          "$ref": "bundle.schema.json#/$defs/opaqueId"
        },
        "knownBy": {
          "$ref": "bundle.schema.json#/$defs/knownBy"
        },
        "ext": {
          "$ref": "bundle.schema.json#/$defs/ext"
        }
      }
    },
    "pinned": {
      "type": "boolean"
    },
    "hidden": {
      "type": "boolean"
    },
    "ext": {
      "$ref": "bundle.schema.json#/$defs/ext"
    }
  },
  "allOf": [
    {
      "description": "Only system messages may have empty content.",
      "if": {
        "not": {
          "properties": {
            "from": {
              "const": "system"
            }
          }
        }
      },
      "then": {
        "properties": {
          "content": {
            "minItems": 1
          }
        }
      }
    },
    {
      "description": "A records-only message carries changes, and on a root an opening and entries, and no content.",
      "if": {
        "properties": {
          "content": {
            "maxItems": 0
          }
        }
      },
      "then": {
        "required": [
          "changes"
        ],
        "properties": {
          "from": {
            "const": "system"
          },
          "summary": false,
          "activated": false,
          "char": false,
          "pinned": {
            "const": false
          }
        },
        "if": {
          "required": [
            "parent"
          ]
        },
        "then": {
          "properties": {
            "entries": false
          }
        }
      }
    },
    {
      "description": "Only a root that is a system message names an opening.",
      "if": {
        "anyOf": [
          {
            "required": [
              "parent"
            ]
          },
          {
            "not": {
              "properties": {
                "from": {
                  "const": "system"
                }
              }
            }
          }
        ]
      },
      "then": {
        "properties": {
          "opening": false
        }
      }
    },
    {
      "description": "Only model messages name the character they were written for, and record activated entries.",
      "if": {
        "not": {
          "properties": {
            "from": {
              "const": "model"
            }
          }
        }
      },
      "then": {
        "properties": {
          "char": false,
          "activated": false
        }
      }
    },
    {
      "description": "A root is a system message made from an opening, or a player message.",
      "if": {
        "not": {
          "required": [
            "parent"
          ]
        }
      },
      "then": {
        "anyOf": [
          {
            "required": [
              "opening"
            ],
            "properties": {
              "from": {
                "const": "system"
              }
            }
          },
          {
            "properties": {
              "from": {
                "const": "player"
              }
            }
          }
        ]
      }
    }
  ],
  "$defs": {
    "change": {
      "type": "object",
      "required": [
        "by",
        "set"
      ],
      "additionalProperties": false,
      "properties": {
        "by": {
          "enum": [
            "rules",
            "player",
            "model"
          ]
        },
        "set": {
          "$ref": "bundle.schema.json#/$defs/stateValues"
        },
        "event": {
          "$ref": "bundle.schema.json#/$defs/eventName"
        },
        "outcome": {
          "type": "integer",
          "minimum": 0
        },
        "ext": {
          "$ref": "bundle.schema.json#/$defs/ext"
        }
      },
      "dependentRequired": {
        "outcome": [
          "event"
        ]
      },
      "if": {
        "required": [
          "by"
        ],
        "properties": {
          "by": {
            "not": {
              "const": "rules"
            }
          }
        }
      },
      "then": {
        "properties": {
          "event": false
        }
      }
    }
  }
}
