{
  "$id": "http://schemas.futureordering.com/stores.schema.json",
  "$schema": "http://json-schema.org/draft-08/schema",
  "definitions": {
    "station": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "staffTitle": {
          "type": "object",
          "$ref": "#/definitions/translatableContent"
        },
        "staffDescription": {
          "type": "object",
          "$ref": "#/definitions/translatableContent"
        },
        "responsibilities": {
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[a-z0-9\\-]+$"
          }
        }
      }
    },
    "taxCalculationMethod": {
      "type": "string",
      "default": "ItemPerUnit",
      "description": "How to calculate VAT for an order.",
      "enum": [
        "ItemPerUnit",
        "LineSummed",
        "OrderSummed",
        "LinePerUnit",
        "ItemSummed"
      ]
    },
    "orderCostEstimator": {
      "type": "object",
      "required": [
        "type"
      ],
      "additionalProperties": false,
      "properties": {
        "type": {
          "description": "PointsPerOrder is used for slot time. OrderBasketPoints is used with promise time",
          "type": "string",
          "enum": [
            "PointsPerOrder",
            "OrderBasketPoints"
          ]
        }
      }
    },
    "pointsPerOrder": {},
    "capacity": {
      "description": "Describes the capacity rules",
      "type": "object",
      "required": [
        "conditions",
        "schedule"
      ],
      "additionalProperties": false,
      "properties": {
        "conditions": {
          "type": "array",
          "items": {
            "type": "object",
            "anyOf": [
              {
                "$ref": "#/definitions/specificdates"
              },
              {
                "$ref": "#/definitions/dayofweek"
              },
              {
                "$ref": "#/definitions/betweendates"
              },
              {
                "$ref": "#/definitions/always"
              },
              {
                "$ref": "#/definitions/never"
              }
            ]
          }
        },
        "schedule": {
          "type": "array",
          "items": {
            "type": "object",
            "$ref": "#/definitions/openInstance"
          }
        }
      }
    },
    "translatableContent": {
      "description": "A value that can have translations",
      "examples": [
        {
          "value": "Coffee",
          "translations": {
            "sv-SE": "Kaffe",
            "en-GB": "Coffee"
          }
        }
      ],
      "$comment": "Should this have patternProperty instead of additionalProperties, eg. enforce format of the property keys?",
      "type": "object",
      "required": [
        "value"
      ],
      "additionalProperties": false,
      "properties": {
        "value": {
          "type": "string"
        },
        "translations": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        },
        "overrides": {
          "type": "object",
          "additionalProperties": {
            "type": "object",
            "$ref": "#/definitions/translatableContent"
          }
        }
      }
    },
    "menu": {
      "description": "Configuration for the menu used for this order type. If you include multiple menus for the order type, the menu instance will include a union of the categories and products in all menus included. If an item appears in multiple included menus with different price groups, the last version of the item with prices will the one included in the menu instance.",
      "examples": [
        {
          "referencedMenuDefinitionId": "789",
          "referencedPriceGroupId": "93474"
        }
      ],
      "type": "object",
      "required": [
        "referencedMenuDefinitionId",
        "referencedPriceGroupId"
      ],
      "additionalProperties": false,
      "properties": {
        "referencedMenuDefinitionId": {
          "description": "The id of the menu which defined which categories and items to use.",
          "type": "string",
          "pattern": "^[-+]?\\d*$"
        },
        "referencedPriceGroupId": {
          "description": "The id of the price group which defines the prices for all items included in the menu.",
          "type": "string",
          "pattern": "^[-+]?\\d*$"
        }
      }
    },
    "location": {
      "description": "Describes the location of a store.",
      "examples": [
        {
          "address": {
            "postalCode": "11147",
            "street": "Kungsträdgårdsgatan 20",
            "city": "Stockholm",
            "countryName": "Sweden",
            "countryIsoCode": "SE"
          },
          "position": {
            "latitude": 59.33274,
            "longitude": 18.07174
          }
        }
      ],
      "type": "object",
      "required": [
        "address"
      ],
      "additionalProperties": false,
      "properties": {
        "address": {
          "type": "object",
          "required": [
            "countryIsoCode"
          ],
          "properties": {
            "postalCode": {
              "description": "The postal code of the store, displayed in store information pages.",
              "type": "string"
            },
            "street": {
              "description": "The street address of the store, displayed in store information pages.",
              "type": "string"
            },
            "city": {
              "description": "The name of the city which the store is in, displayed in store information pages.",
              "type": "string"
            },
            "countryName": {
              "description": "The country name which the store is in, displayed in store information pages",
              "type": "string"
            },
            "countryIsoCode": {
              "description": "The country iso code of the store, used for determining which country site the store should be displayed on",
              "$comment": "Needs to be uppercase? We should have enum for this I guess.",
              "type": "string"
            }
          }
        },
        "position": {
          "type": "object",
          "required": [
            "latitude",
            "longitude"
          ],
          "properties": {
            "latitude": {
              "type": "number"
            },
            "longitude": {
              "type": "number"
            }
          }
        }
      }
    },
    "specificdates": {
      "description": "Open a list of specific dates.",
      "$comment": "Better description?",
      "examples": [
        {
          "type": "specificdates",
          "dates": [
            "2020-12-31",
            "2021-12-31"
          ]
        }
      ],
      "type": "object",
      "required": [
        "type",
        "dates"
      ],
      "additionalProperties": false,
      "properties": {
        "type": {
          "type": "string",
          "const": "specificdates"
        },
        "dates": {
          "description": "The dates for which this condition should evaluate to true.",
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "string",
            "format": "date"
          }
        }
      }
    },
    "dayofweek": {
      "description": "Open on specific week days.",
      "examples": [
        {
          "type": "dayofweek",
          "days": [
            "Monday",
            "Tuesday",
            "Thursday"
          ]
        }
      ],
      "type": "object",
      "required": [
        "type",
        "days"
      ],
      "additionalProperties": false,
      "properties": {
        "type": {
          "type": "string",
          "const": "dayofweek"
        },
        "days": {
          "description": "List of days to evaluate as true. No duplicates.",
          "$comment": "No duplicates right?",
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "Monday",
              "Tuesday",
              "Wednesday",
              "Thursday",
              "Friday",
              "Saturday",
              "Sunday"
            ]
          },
          "uniqueItems": true
        }
      }
    },
    "betweendates": {
      "description": "Inclusive list of which days to evaluate to true.",
      "examples": [
        {
          "type": "betweendates",
          "fromIncl": "2020-03-29",
          "toIncl": "2025-04-01"
        }
      ],
      "type": "object",
      "required": [
        "type",
        "fromIncl",
        "toIncl"
      ],
      "additionalProperties": false,
      "properties": {
        "type": {
          "type": "string",
          "const": "betweendates"
        },
        "toIncl": {
          "description": "Determines the first day to which this condition should evaluate to true for, from date is inclusive.",
          "type": "string",
          "format": "date"
        },
        "fromIncl": {
          "description": "Determines the last day to which this condition should evaluate to true for, to date is inclusive.",
          "type": "string",
          "format": "date"
        }
      }
    },
    "always": {
      "description": "The condition with type \"always\" does not use any properties and will always evaluate to true.",
      "examples": [
        {
          "type": "always"
        }
      ],
      "type": "object",
      "required": [
        "type"
      ],
      "additionalProperties": false,
      "properties": {
        "type": {
          "type": "string"
        }
      }
    },
    "never": {
      "description": "The condition with type \"never\" does not use any properties and will always evel evaluate to false.",
      "examples": [
        {
          "type": "never"
        }
      ],
      "type": "object",
      "required": [
        "type"
      ],
      "additionalProperties": false,
      "properties": {
        "type": {
          "type": "string"
        }
      }
    },
    "production": {
      "description": "Describes the production capacity for the store",
      "type": "object",
      "required": [
        "timeslotDuration",
        "orderCostEstimator",
        "capacity"
      ],
      "additionalProperties": false,
      "properties": {
        "timeslotDuration": {
          "description": "The duration of a timeslot in ISO-8601 format",
          "type": "string"
        },
        "orderCostEstimator": {
          "type": "object",
          "$ref": "#/definitions/orderCostEstimator"
        },
        "capacity": {
          "type": "array",
          "items": {
            "type": "object",
            "$ref": "#/definitions/capacity"
          }
        }
      }
    },
    "openInstance": {
      "description": "It is currently not supported to have multiple separate blocks of opening hours for the same day, e.g. Open from 08:00 - 14:00 and also open from 16:00 - 20:00 is not currently supported. t is currently not supported to have multiple separate blocks of opening hours for the same day, e.g. Open from 08:00 - 14:00 and also open from 16:00 - 20:00 is not currently supported.",
      "type": "object",
      "required": [
        "from",
        "to"
      ],
      "additionalProperties": false,
      "properties": {
        "from": {
          "description": "Sets the start of the opening hour block, i.e. when the store opens.",
          "type": "string",
          "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$"
        },
        "to": {
          "description": "Sets the end of the opening hour block, i.e. when the store closes.",
          "type": "string",
          "pattern": "^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$"
        },
        "toNextDay": {
          "description": "Defaults to false. Determines whether the `to` time should be considered being on the same day as the date this entry is used to set opening hours for or if the `to` time should be considered part of the next day.",
          "type": "boolean"
        },
        "capacityPerTimeslot": {
          "type": "integer"
        }
      }
    },
    "openingHours": {
      "description": "The first opening hours entry for which all conditions evaluate to true will be used to set opening hours for a specific date, e.g. if rule R1 has a specificdate condition for New Years Eve this year and rule R2 has condition \"always\", New Years Eve this year will get opening hours from the one that occurs first in the array.",
      "examples": [
        {
          "conditions": [
            {
              "type": "specificdates",
              "dates": [
                "2020-12-31",
                "2021-12-31"
              ]
            }
          ],
          "open": [
            {
              "from": "18:00",
              "to": "02:00",
              "toNextDay": true
            }
          ]
        },
        {
          "conditions": [
            {
              "type": "specificdates",
              "dates": [
                "2020-06-05"
              ]
            }
          ],
          "open": [
            {
              "from": "10:00",
              "to": "08:00"
            }
          ]
        },
        {
          "conditions": [
            {
              "type": "specificdates",
              "dates": [
                "2020-12-24",
                "2021-12-24"
              ]
            }
          ],
          "open": []
        },
        {
          "conditions": [
            {
              "type": "dayofweek",
              "days": [
                "Monday",
                "Tuesday",
                "Thursday"
              ]
            },
            {
              "type": "betweendates",
              "fromIncl": "2020-03-29",
              "toIncl": "2025-04-01"
            }
          ],
          "open": [
            {
              "from": "10:00",
              "to": "16:00"
            }
          ]
        },
        {
          "conditions": [
            {
              "type": "dayofweek",
              "days": [
                "Monday",
                "Tuesday",
                "Wednesday",
                "Thursday",
                "Friday",
                "Saturday"
              ]
            }
          ],
          "open": [
            {
              "from": "00:00",
              "to": "00:00",
              "toNextDay": true
            }
          ]
        },
        {
          "conditions": [
            {
              "type": "dayofweek",
              "days": [
                "Sunday"
              ]
            }
          ],
          "open": [
            {
              "from": "00:00",
              "to": "00:00",
              "toNextDay": true
            }
          ]
        },
        {
          "conditions": [
            {
              "type": "always"
            }
          ],
          "open": [
            {
              "from": "00:00",
              "to": "00:00",
              "toNextDay": true
            }
          ]
        }
      ],
      "type": "object",
      "required": [
        "conditions",
        "open"
      ],
      "additionalProperties": false,
      "properties": {
        "conditions": {
          "type": "array",
          "items": {
            "type": "object",
            "anyOf": [
              {
                "$ref": "#/definitions/specificdates"
              },
              {
                "$ref": "#/definitions/dayofweek"
              },
              {
                "$ref": "#/definitions/betweendates"
              },
              {
                "$ref": "#/definitions/always"
              }
            ]
          },
          "minItems": 1
        },
        "open": {
          "type": "array",
          "items": {
            "type": "object",
            "$ref": "#/definitions/openInstance"
          }
        }
      }
    },
    "store": {
      "type": "object",
      "required": [
        "title",
        "orderClasses",
        "location",
        "tzdbTimeZoneId",
        "openingHours",
        "production"
      ],
      "additionalProperties": false,
      "properties": {
        "taxCalculationMethod": {
          "description": "How to calculate VAT for an order. If not supplied it will default to itemPerUnit",
          "type": "string",
          "$ref": "#/definitions/taxCalculationMethod"
        },
        "defaultStaffCultureCode": {
          "type": "string"
        },
        "title": {
          "type": "object",
          "$ref": "#/definitions/translatableContent"
        },
        "orderClasses": {
          "type": "object",
          "properties": {
            "takeaway": {
              "type": "object",
              "required": [
                "menuDefinitionId"
              ],
              "properties": {
                "menuDefinitionId": {
                  "type": "string"
                }
              }
            }
          }
        },
        "contactInformation": {
          "type": "object",
          "properties": {
            "phoneNumber": {
              "type": "string"
            }
          }
        },
        "location": {
          "type": "object",
          "$ref": "#/definitions/location"
        },
        "images": {
          "type": "object",
          "properties": {
            "default": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "object",
                  "required": [
                    "value"
                  ],
                  "properties": {
                    "value": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "tzdbTimeZoneId": {
          "type": "string"
        },
        "openingHours": {
          "type": "array",
          "items": {
            "type": "object",
            "$ref": "#/definitions/openingHours"
          }
        },
        "production": {
          "type": "object",
          "$ref": "#/definitions/production"
        },
        "mappingDetails": {
          "type": "object",
          "additionalProperties": true
        },
        "stations": {
          "type": "object",
          "additionalProperties": false,
          "patternProperties": {
            "^[a-z0-9]+$": {
              "type": "object",
              "$ref": "#/definitions/station"
            }
          }
        }
      }
    }
  },
  "type": "object",
  "required": [
    "stores"
  ],
  "properties": {
    "stores": {
      "type": "object",
      "patternProperties": {
        "^[-+]?\\d*$": {
          "type": "object",
          "$ref": "#/definitions/store"
        }
      }
    }
  }
}