{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$id": "https://github.com/openstreetmap/id-tagging-schema/raw/main/schemas/field.json",
    "title": "Field",
    "description": "A reusable form element for presets",
    "type": "object",
    "properties": {
        "key": {
            "description": "Tag key whose value is to be displayed",
            "type": "string",
            "minLength": 1
        },
        "keys": {
            "description": "Tag keys whose value is to be displayed",
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
                "type": "string",
                "minLength": 1
            }
        },
        "reference": {
            "description": "Taginfo documentation parameters (to be used when a field manages multiple tags)",
            "anyOf": [
                {
                    "type": "object",
                    "properties": {
                        "key": {
                            "description": "For documentation of a key",
                            "type": "string",
                            "minLength": 1
                        },
                        "value": {
                            "description": "For documentation of a tag (key and value)",
                            "type": "string",
                            "minLength": 1
                        }
                    },
                    "additionalProperties": false,
                    "required": [
                        "key"
                    ]
                },
                {
                    "type": "object",
                    "properties": {
                        "rtype": {
                            "description": "For documentation of a relation type",
                            "type": "string",
                            "minLength": 1
                        }
                    },
                    "additionalProperties": false,
                    "required": [
                        "rtype"
                    ]
                }
            ]
        },
        "type": {
            "description": "Type of field",
            "type": "string",
            "enum": [
                "access",
                "address",
                "check",
                "colour",
                "combo",
                "date",
                "defaultCheck",
                "directionalCombo",
                "email",
                "identifier",
                "integer",
                "lanes",
                "localized",
                "manyCombo",
                "multiCombo",
                "networkCombo",
                "number",
                "onewayCheck",
                "radio",
                "restrictions",
                "roadheight",
                "roadspeed",
                "schedule",
                "semiCombo",
                "structureRadio",
                "tel",
                "text",
                "textarea",
                "typeCombo",
                "url",
                "wikidata",
                "wikipedia"
            ]
        },
        "label": {
            "description": "English label for the field caption. A field can reference the label of another by using that field's identifier contained in brackets (e.g. {field}), in which case also the field's terms will be referenced from that field.",
            "type": "string",
            "minLength": 1
        },
        "geometry": {
            "description": "If specified, only show the field for these kinds of geometry",
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
                "$ref": "#/$defs/Geometry"
            }
        },
        "default": {
            "description": "The default value for this field",
            "type": "string",
            "minLength": 1
        },
        "options": {
            "description": "List of untranslatable string suggestions (combo fields)",
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
                "type": "string",
                "minLength": 1
            }
        },
        "autoSuggestions": {
            "description": "If true, the top values from TagInfo will be suggested in the dropdown (combo fields only)",
            "type": "boolean",
            "default": true
        },
        "customValues": {
            "description": "If true, the user can type their own value in addition to any listed in `options` or `strings.options` (combo fields only)",
            "type": "boolean",
            "default": true
        },
        "universal": {
            "description": "If true, this field will appear in the Add Field list for all presets",
            "type": "boolean",
            "default": false
        },
        "placeholder": {
            "description": "Placeholder text for this field. A field can reference the placeholder text of another by using that field's identifier contained in brackets, like {field}.",
            "type": "string",
            "minLength": 1
        },
        "strings": {
            "description": "Strings sent to transifex for translation",
            "type": "object",
            "minProperties": 1,
            "additionalProperties": false,
            "properties": {
                "options": {
                    "description": "Translatable options (combo fields).",
                    "type": "object",
                    "minProperties": 1,
                    "additionalProperties": {
                        "oneOf": [
                            {
                                "type": "string",
                                "minLength": 1
                            },
                            {
                                "type": "object",
                                "properties": {
                                    "title": {
                                        "type": "string",
                                        "minLength": 1
                                    },
                                    "description": {
                                        "type": "string",
                                        "minLength": 1
                                    }
                                },
                                "required": [
                                    "title",
                                    "description"
                                ],
                                "additionalProperties": false
                            }
                        ]
                    }
                },
                "types": {
                    "description": "Translatable types (directionalCombo and access only).",
                    "type": "object",
                    "minProperties": 1,
                    "additionalProperties": {
                        "type": "string",
                        "minLength": 1
                    }
                },
                "placeholders": {
                    "description": "Translatable placeholders of fields with subfields (address only).",
                    "type": "object",
                    "minProperties": 1,
                    "additionalProperties": {
                        "type": "string",
                        "minLength": 1
                    }
                },
                "labels": {
                    "description": "Translatable labels of fields with subfields (address only).",
                    "type": "object",
                    "minProperties": 1,
                    "additionalProperties": {
                        "type": "string",
                        "minLength": 1
                    }
                }
            }
        },
        "stringsCrossReference": {
            "description": "A field can reference strings of another by using that field's identifier contained in brackets, like {field}.",
            "type": "string",
            "minLength": 1
        },
        "snake_case": {
            "description": "If true, replace spaces with underscores in the tag value (combo fields only)",
            "type": "boolean",
            "default": true
        },
        "caseSensitive": {
            "description": "If true, allow case sensitive field values (combo fields only)",
            "type": "boolean",
            "default": false
        },
        "allowDuplicates": {
            "description": "If true, duplicate values are allowed (semiCombo fields only)",
            "type": "boolean",
            "default": false
        },
        "minValue": {
            "description": "Minimum field value (number fields only)",
            "type": "integer"
        },
        "maxValue": {
            "description": "Maximum field value (number fields only)",
            "type": "integer"
        },
        "increment": {
            "description": "The amount the stepper control should add or subtract (number fields only)",
            "minimum": 1,
            "type": "integer"
        },
        "prerequisiteTag": {
            "description": "Tagging constraint for showing this field in the editor",
            "oneOf": [
                {
                    "$id": "requires-key-any-value",
                    "type": "object",
                    "properties": {
                        "key": {
                            "description": "The key of the required tag",
                            "type": "string",
                            "minLength": 1
                        }
                    },
                    "additionalProperties": false,
                    "required": [
                        "key"
                    ]
                },
                {
                    "$id": "requires-key-equals-value",
                    "type": "object",
                    "properties": {
                        "key": {
                            "description": "The key of the required tag",
                            "type": "string",
                            "minLength": 1
                        },
                        "value": {
                            "description": "The value that the tag must have. (alternative to 'valueNot')",
                            "type": "string",
                            "minLength": 1
                        }
                    },
                    "additionalProperties": false,
                    "required": [
                        "key",
                        "value"
                    ]
                },
                {
                    "$id": "requires-key-equals-values",
                    "type": "object",
                    "properties": {
                        "key": {
                            "description": "The key of the required tag",
                            "type": "string",
                            "minLength": 1
                        },
                        "values": {
                            "description": "The values that the tag must have. (alternative to 'valuesNot')",
                            "type": "array",
                            "items": {
                                "type": "string",
                                "minLength": 1
                            },
                            "minItems": 1
                        }
                    },
                    "additionalProperties": false,
                    "required": [
                        "key",
                        "values"
                    ]
                },
                {
                    "$id": "requires-key-not-value",
                    "type": "object",
                    "properties": {
                        "key": {
                            "description": "The key of the required tag",
                            "type": "string",
                            "minLength": 1
                        },
                        "valueNot": {
                            "description": "The value that the tag cannot have. (alternative to 'value')",
                            "type": "string"
                        }
                    },
                    "additionalProperties": false,
                    "required": [
                        "key",
                        "valueNot"
                    ]
                },
                {
                    "$id": "requires-key-not-values",
                    "type": "object",
                    "properties": {
                        "key": {
                            "description": "The key of the required tag",
                            "type": "string",
                            "minLength": 1
                        },
                        "valuesNot": {
                            "description": "The values that the tag cannot have. (alternative to 'values')",
                            "type": "array",
                            "items": {
                                "type": "string"
                            },
                            "minItems": 1
                        }
                    },
                    "additionalProperties": false,
                    "required": [
                        "key",
                        "valuesNot"
                    ]
                },
                {
                    "$id": "requires-not-key",
                    "type": "object",
                    "properties": {
                        "keyNot": {
                            "description": "A key that must not be present",
                            "type": "string",
                            "minLength": 1
                        }
                    },
                    "additionalProperties": false,
                    "required": [
                        "keyNot"
                    ]
                }
            ]
        },
        "terms": {
            "description": "English synonyms or related search terms",
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
                "type": "string",
                "minLength": 1
            }
        },
        "locationSet": {
            "description": "An object specifying the IDs of regions where this field is or isn't valid. See: https://github.com/ideditor/location-conflation",
            "type": "object",
            "minProperties": 1,
            "properties": {
                "include": {
                    "type": "array",
                    "minItems": 1,
                    "uniqueItems": true,
                    "items": {
                        "type": "string",
                        "minLength": 1
                    }
                },
                "exclude": {
                    "type": "array",
                    "minItems": 1,
                    "uniqueItems": true,
                    "items": {
                        "type": "string",
                        "minLength": 1
                    }
                }
            },
            "additionalProperties": false
        },
        "locationSetCrossReference": {
            "type": "string",
            "minLength": 1,
            "pattern": "^\\{.+\\}$",
            "description": "An string referencing another preset which has a locationSet"
        },
        "urlFormat": {
            "description": "Permalink URL for `identifier` fields. Must contain a {value} placeholder",
            "type": "string",
            "minLength": 1
        },
        "pattern": {
            "description": "Regular expression that a valid `identifier` value is expected to match",
            "type": "string",
            "minLength": 1
        },
        "usage": {
            "description": "The manner and context in which the field is used",
            "type": "string",
            "enum": [
                "preset",
                "changeset",
                "manual",
                "group"
            ]
        },
        "icons": {
            "description": "For combo and radio fields: Name of icons which represents different values of this field",
            "type": "object",
            "minProperties": 1,
            "additionalProperties": {
                "type": "string",
                "minLength": 1
            }
        },
        "iconsCrossReference": {
            "description": "A field can reference icons of another by using that field's identifier contained in brackets, like {field}.",
            "type": "string",
            "minLength": 1
        }
    },
    "additionalProperties": false,
    "required": [
        "type",
        "label"
    ],
    "anyOf": [
        {
            "$id": "field-type-without-key-nor-keys",
            "properties": {
                "type": {
                    "enum": [
                        "restrictions"
                    ]
                }
            },
            "allOf": [
                {
                    "not": {
                        "required": [
                            "key"
                        ]
                    }
                },
                {
                    "not": {
                        "required": [
                            "keys"
                        ]
                    }
                }
            ]
        },
        {
            "$id": "field-type-with-key-optional-keys",
            "properties": {
                "type": {
                    "enum": [
                        "email",
                        "url",
                        "tel",
                        "text",
                        "number"
                    ]
                }
            },
            "required": [
                "key"
            ]
        },
        {
            "$id": "field-type-with-key-and-keys",
            "properties": {
                "type": {
                    "enum": [
                        "address",
                        "wikipedia",
                        "wikidata",
                        "directionalCombo"
                    ]
                }
            },
            "required": [
                "key",
                "keys"
            ]
        },
        {
            "$id": "field-type-with-key-or-keys",
            "allOf": [
                {
                    "not": {
                        "properties": {
                            "type": {
                                "enum": [
                                    "restriction",
                                    "email",
                                    "url",
                                    "tel",
                                    "text",
                                    "number",
                                    "address",
                                    "wikipedia",
                                    "wikidata",
                                    "directionalCombo"
                                ]
                            }
                        }
                    }
                },
                {
                    "oneOf": [
                        {
                            "required": [
                                "key"
                            ]
                        },
                        {
                            "required": [
                                "keys"
                            ]
                        }
                    ]
                }
            ]
        }
    ],
    "$defs": {
        "Geometry": {
            "type": "string",
            "enum": [
                "point",
                "vertex",
                "line",
                "area",
                "relation"
            ]
        }
    }
}
