{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "descent-glovepie map",
    "description": "Describes the mappings for generating a GlovePIE script.",
    "type": "object",
    "properties": {
        "input": {
            "description": "Input prefix that is applied to all inputs.  For instance, if you set this to \"Sixaxis1\" and define a button mapping for \"Square\", then the generated script will use \"Sixaxis1.Square\".  This parameter is optional; if not specified, no prefix is applied to inputs.",
            "type": "string"
        },
        "alias": {
            "description": "Input aliases.  Allows arbitrary GlovePIE code to be used as an input.",
            "type": "object",
            "patternProperties": {
                "^[A-Za-z][A-Za-z0-9]*$": {
                    "description": "Alias for an input.",
                    "type": "string"
                }
            }
        },
        "shift": {
            "description": "List of inputs that can be used as shift buttons.",
            "type": "array",
            "items": {
                "type": "string",
                "pattern": "^:?[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)*$"
            },
            "_uniqueItems": true
        },
        "axis": {
            "description": "Mappings for analog inputs to virtual joystick axes.  Each property name is an input, and each value is the output.",
            "type": "object",
            "patternProperties": {
                "^:?[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)*$": {
                    "description": "Mapping of an analog input to an output.  The output may be inverted by putting a dash (-) at the beginning of the value.",
                    "type": "string",
                    "pattern": "^-?[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)*$"
                }
            },
            "additionalProperties": false
        },
        "button": {
            "description": "Mappings for digital inputs to virtual joystick buttons, keyboard keys, or keyboard macros.  Each property name is an input.",
            "type": "object",
            "patternProperties": {
                "^:?[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)*$": {
                    "oneOf": [
                        {
                            "description": "Simple mapping for this digital input.",
                            "$ref": "#/definitions/output"
                        },
                        {
                            "description": "Mappings for this digital input.  The property names are the shift button inputs, except \"normal\" which is the unshifted mapping.",
                            "type": "object",
                            "properties": {
                                "normal": {
                                    "description": "Normal, unshifted mapping for this digital input.",
                                    "$ref": "#/definitions/output"
                                }
                            },
                            "patternProperties": {
                                "^[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)*$": {
                                    "description": "Shifted mapping for this digital input.  The property name is the shift button input.",
                                    "$ref": "#/definitions/output"
                                }
                            }
                        }
                    ]
                }
            },
            "additionalProperties": false
        },
        "throttle": {
            "description": "Special mapping for using two buttons as a joystick axis and optional virtual button that indicates when both buttons are pressed.",
            "type": "object",
            "properties": {
                "axis": {
                    "description": "Virtual joystick axis to use for the analog output.",
                    "type": "string",
                    "pattern": "^[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)*$"
                },
                "button": {
                    "description": "Virtual joystick button to use for the digital output indicating when both buttons are pressed.",
                    "type": "string",
                    "pattern": "^[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)*$"
                },
                "forwardButton": {
                    "description": "Virtual joystick button to use for the digital forward output.",
                    "type": "string",
                    "pattern": "^[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)*$"
                },
                "reverseButton": {
                    "description": "Virtual joystick button to use for the digital reverse output.",
                    "type": "string",
                    "pattern": "^[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)*$"
                },
                "forwardDigital": {
                    "description": "Digital input indicating when the button used for forward is pressed, if available.",
                    "type": "string",
                    "pattern": "^:?[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)*$"
                },
                "forwardAnalog": {
                    "description": "Analog input indicating how far the button used for forward is pressed, if available.",
                    "type": "string",
                    "pattern": "^:?[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)*$"
                },
                "reverseDigital": {
                    "description": "Digital input indicating when the button used for reverse is pressed, if available.",
                    "type": "string",
                    "pattern": "^:?[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)*$"
                },
                "reverseAnalog": {
                    "description": "Analog input indicating how far the button used for reverse is pressed, if available.",
                    "type": "string",
                    "pattern": "^:?[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)*$"
                },
                "analogThreshold": {
                    "description": "Threshold beyond which an analog button input is considered pressed for programming logic purposes.  This value is only used if a digital input is not specified for forward or reverse.",
                    "type": "number",
                    "minimum": 0,
                    "minimumExclusive": false,
                    "maximum": 1,
                    "maximumExclusive": true
                }
            },
            "additionalProperties": false,
            "allOf": [
                {
                    "anyOf": [
                        {
                            "required": [
                                "axis"
                            ]
                        },
                        {
                            "required": [
                                "button"
                            ]
                        },
                        {
                            "required": [
                                "forwardButton"
                            ]
                        },
                        {
                            "required": [
                                "reverseButton"
                            ]
                        }
                    ]
                },
                {
                    "anyOf": [
                        {
                            "required": [
                                "forwardDigital"
                            ]
                        },
                        {
                            "required": [
                                "forwardAnalog"
                            ]
                        }
                    ]
                },
                {
                    "anyOf": [
                        {
                            "required": [
                                "reverseDigital"
                            ]
                        },
                        {
                            "required": [
                                "reverseAnalog"
                            ]
                        }
                    ]
                }
            ]
        }
    },
    "additionalProperties": false,
    "required": [
        "button"
    ],
    "definitions": {
        "simpleOutput": {
            "description": "Output assignment to a simple button or key.",
            "type": "string",
            "pattern": "^[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)*$"
        },
        "macroOutput": {
            "description": "Output assignment to a keyboard macro.",
            "type": "string",
            "pattern": "^~[A-Za-z][A-Za-z0-9]*([- ][A-Za-z][A-Za-z0-9]*)*$"
        },
        "output": {
            "oneOf": [
                {
                    "$ref": "#/definitions/simpleOutput"
                },
                {
                    "$ref": "#/definitions/macroOutput"
                }
            ]
        }
    }
}