{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://docs.insyde.one/edge-template.schema.json",
  "title": "Edge Template Config",
  "description": "JSON Schema for an Edge Template's config.json. Validates the field declarations (fields[]), schema metadata (meta), presets, and variants. See https://docs.insyde.one/tutorial-edge-templates-overview.html for the prose docs.",
  "type": "object",
  "required": ["fields"],
  "additionalProperties": false,
  "properties": {
    "$schema": { "type": "string", "format": "uri" },
    "fields": {
      "type": "array",
      "minItems": 1,
      "items": { "$ref": "#/$defs/field" }
    },
    "meta":     { "$ref": "#/$defs/meta" },
    "presets":  { "type": "array", "items": { "$ref": "#/$defs/preset" } },
    "variants": { "type": "object", "additionalProperties": { "$ref": "#/$defs/variant" } }
  },

  "$defs": {

    "identifier": {
      "type": "string",
      "pattern": "^[a-zA-Z][a-zA-Z0-9_]*$",
      "description": "camelCase identifier (letters, digits, underscore; must start with a letter)"
    },

    "shortKey": {
      "type": "string",
      "minLength": 1,
      "maxLength": 16,
      "pattern": "^[a-zA-Z][a-zA-Z0-9]*$",
      "description": "Short prefix used in the querystring (1-16 chars, letters and digits only)"
    },

    "option": {
      "type": "object",
      "required": ["value", "text"],
      "additionalProperties": false,
      "properties": {
        "value": { "type": "string", "minLength": 1 },
        "text":  { "type": "string", "minLength": 1 }
      }
    },

    "fieldType": {
      "type": "string",
      "enum": [
        "text", "textarea", "boolean", "dropdown", "color", "file", "url",
        "date", "number", "slider", "normalized", "counter", "radio",
        "colorBinding", "table",
        "repeater", "chartData", "presetSelection", "variant", "timer",
        "overlayRegions", "actionButton", "dataConnector", "map", "video", "richtext"
      ]
    },

    "fieldBase": {
      "type": "object",
      "required": ["key", "name", "label", "type", "default"],
      "properties": {
        "key":   { "$ref": "#/$defs/shortKey" },
        "name":  { "$ref": "#/$defs/identifier" },
        "label": { "type": "string", "minLength": 1 },
        "type":  { "$ref": "#/$defs/fieldType" },
        "tip":   { "type": "string" }
      }
    },

    "field": {
      "allOf": [
        { "$ref": "#/$defs/fieldBase" },
        {
          "oneOf": [
            { "$ref": "#/$defs/field.text" },
            { "$ref": "#/$defs/field.textarea" },
            { "$ref": "#/$defs/field.boolean" },
            { "$ref": "#/$defs/field.dropdown" },
            { "$ref": "#/$defs/field.color" },
            { "$ref": "#/$defs/field.file" },
            { "$ref": "#/$defs/field.url" },
            { "$ref": "#/$defs/field.date" },
            { "$ref": "#/$defs/field.number" },
            { "$ref": "#/$defs/field.slider" },
            { "$ref": "#/$defs/field.normalized" },
            { "$ref": "#/$defs/field.counter" },
            { "$ref": "#/$defs/field.radio" },
            { "$ref": "#/$defs/field.colorBinding" },
            { "$ref": "#/$defs/field.table" },
            { "$ref": "#/$defs/field.roadmap" }
          ]
        }
      ]
    },

    "field.text": {
      "type": "object",
      "properties": {
        "type":     { "const": "text" },
        "default":  { "type": "string" },
        "maxChars": { "type": "integer", "minimum": 1 }
      },
      "required": ["type"]
    },

    "field.textarea": {
      "type": "object",
      "properties": {
        "type":     { "const": "textarea" },
        "default":  { "type": "string" },
        "maxChars": { "type": "integer", "minimum": 1 },
        "rows":     { "type": "integer", "minimum": 1, "maximum": 40 }
      },
      "required": ["type"]
    },

    "field.boolean": {
      "type": "object",
      "properties": {
        "type":    { "const": "boolean" },
        "default": { "type": "boolean" }
      },
      "required": ["type"]
    },

    "field.dropdown": {
      "type": "object",
      "properties": {
        "type":    { "const": "dropdown" },
        "default": { "type": "string" },
        "options": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/option" } }
      },
      "required": ["type", "options"]
    },

    "field.color": {
      "type": "object",
      "properties": {
        "type":    { "const": "color" },
        "default": { "type": "string", "pattern": "^(#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|rgba?\\([^)]+\\)|[a-zA-Z]+)$" }
      },
      "required": ["type"]
    },

    "field.file": {
      "type": "object",
      "properties": {
        "type":    { "const": "file" },
        "default": { "type": "string" },
        "accept":  { "type": "string", "minLength": 1 }
      },
      "required": ["type"]
    },

    "field.url": {
      "type": "object",
      "properties": {
        "type":     { "const": "url" },
        "default":  { "type": "string" },
        "maxChars": { "type": "integer", "minimum": 1 }
      },
      "required": ["type"]
    },

    "field.date": {
      "type": "object",
      "properties": {
        "type":    { "const": "date" },
        "default": { "type": "string" },
        "format":  { "type": "string", "minLength": 1 }
      },
      "required": ["type"]
    },

    "field.number": {
      "type": "object",
      "properties": {
        "type":    { "const": "number" },
        "default": { "type": "number" },
        "min":     { "type": "number" },
        "max":     { "type": "number" },
        "step":    { "type": "number", "exclusiveMinimum": 0 }
      },
      "required": ["type"]
    },

    "field.slider": {
      "type": "object",
      "properties": {
        "type":    { "const": "slider" },
        "default": { "type": "number" },
        "min":     { "type": "number" },
        "max":     { "type": "number" },
        "step":    { "type": "number", "exclusiveMinimum": 0 }
      },
      "required": ["type"]
    },

    "field.normalized": {
      "type": "object",
      "description": "Range and step are fixed (0-100, 0.1) and not configurable.",
      "properties": {
        "type":    { "const": "normalized" },
        "default": { "type": "number", "minimum": 0, "maximum": 100 }
      },
      "required": ["type"]
    },

    "field.counter": {
      "type": "object",
      "properties": {
        "type":    { "const": "counter" },
        "default": { "type": "integer" },
        "min":     { "type": "integer" },
        "max":     { "type": "integer" },
        "step":    { "type": "integer", "exclusiveMinimum": 0 }
      },
      "required": ["type"]
    },

    "field.radio": {
      "type": "object",
      "properties": {
        "type":    { "const": "radio" },
        "default": { "type": "string" },
        "options": { "type": "array", "minItems": 2, "maxItems": 8, "items": { "$ref": "#/$defs/option" } }
      },
      "required": ["type", "options"]
    },

    "field.colorBinding": {
      "type": "object",
      "properties": {
        "type":    { "const": "colorBinding" },
        "default": { "type": "string", "pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$" },
        "palette": { "type": "string", "minLength": 1 }
      },
      "required": ["type", "palette"]
    },

    "field.table": {
      "type": "object",
      "properties": {
        "type":    { "const": "table" },
        "default": { "type": "array" },
        "columns": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/tableColumn" } },
        "minRows": { "type": "integer", "minimum": 0 },
        "maxRows": { "type": "integer", "minimum": 1 }
      },
      "required": ["type", "columns"]
    },

    "field.roadmap": {
      "type": "object",
      "description": "Field types declared in the union but not yet implemented in the editor. Validation only checks the type literal.",
      "properties": {
        "type": {
          "enum": [
            "repeater", "chartData", "presetSelection", "variant", "timer",
            "overlayRegions", "actionButton", "dataConnector", "map", "video", "richtext"
          ]
        }
      },
      "required": ["type"]
    },

    "tableColumnType": {
      "type": "string",
      "enum": ["text", "number", "boolean", "image", "url", "color", "dropdown", "omo"]
    },

    "tableColumn": {
      "type": "object",
      "required": ["key", "label", "type"],
      "additionalProperties": false,
      "properties": {
        "key":      { "$ref": "#/$defs/shortKey" },
        "label":    { "type": "string", "minLength": 1 },
        "type":     { "$ref": "#/$defs/tableColumnType" },
        "width":    { "type": "integer", "minimum": 20, "maximum": 800 },
        "required": { "type": "boolean" },
        "options":  { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/option" } },
        "accept":   { "type": "string", "minLength": 1 },
        "min":      { "type": "number" },
        "max":      { "type": "number" },
        "step":     { "type": "number", "exclusiveMinimum": 0 },
        "default":  {},
        "tip":      { "type": "string" }
      },
      "allOf": [
        {
          "if":   { "properties": { "type": { "enum": ["dropdown", "omo"] } }, "required": ["type"] },
          "then": { "required": ["options"] }
        }
      ]
    },

    "preset": {
      "type": "object",
      "required": ["id", "label", "values"],
      "additionalProperties": false,
      "properties": {
        "id":     { "$ref": "#/$defs/identifier" },
        "label":  { "type": "string", "minLength": 1 },
        "values": { "type": "object" }
      }
    },

    "variant": {
      "type": "object",
      "required": ["label"],
      "additionalProperties": false,
      "properties": {
        "label":          { "type": "string", "minLength": 1 },
        "valueOverrides": { "type": "object" }
      }
    },

    "meta": {
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "version":      { "type": "string", "pattern": "^[0-9]+\\.[0-9]+(\\.[0-9]+)?(-[A-Za-z0-9.\\-]+)?$" },
        "widget":       { "$ref": "#/$defs/identifier" },
        "name":         { "type": "string", "minLength": 1 },
        "description":  { "type": "string" },
        "category":     { "type": "string", "pattern": "^[a-z][a-z0-9-]*$" },
        "author":       { "type": "string" },
        "updated":      { "type": "string", "format": "date" },
        "resolution": {
          "type": "object",
          "required": ["width", "height"],
          "additionalProperties": false,
          "properties": {
            "width":  { "type": "integer", "minimum": 1 },
            "height": { "type": "integer", "minimum": 1 }
          }
        },
        "capabilities": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": ["realtime", "nonRealtime", "transparent"]
          },
          "uniqueItems": true
        },
        "palettes": {
          "type": "object",
          "additionalProperties": {
            "type": "array",
            "minItems": 1,
            "items": { "type": "string", "pattern": "^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$" }
          }
        }
      }
    }

  }
}
