local Schema = require("kong.db.schema")

local Entity = {}


local entity_errors = {
  NO_NILABLE = "%s: Entities cannot have nilable types.",
  NO_FUNCTIONS = "%s: Entities cannot have function types.",
  MAP_KEY_STRINGS_ONLY = "%s: Entities map keys must be strings.",
}


-- Make records in Entities required by default,
-- so that they return their full structure on API queries.
local function make_records_required(field)
  if field.required == nil then
    field.required = true
  end
  for _, f in Schema.each_field(field) do
    if f.type == "record" then
      make_records_required(f)
    end
  end
end


function Entity.new_subschema(schema, key, definition)
  make_records_required(definition)
  definition.required = nil
  return Schema.new_subschema(schema, key, definition)
end


function Entity.new(definition)

  local self, err = Schema.new(definition)
  if not self then
    return nil, err
  end

  for name, field in self:each_field() do
    if field.nilable then
      return nil, entity_errors.NO_NILABLE:format(name)
    end

    if not field.abstract then

      if field.type == "map" then
        if field.keys.type ~= "string" then
          return nil, entity_errors.MAP_KEY_STRINGS_ONLY:format(name)
        end

      elseif field.type == "record" then
        make_records_required(field)

      elseif field.type == "function" then
        return nil, entity_errors.NO_FUNCTIONS:format(name)
      end

    end
  end

  self.new_subschema = Entity.new_subschema

  return self
end


return Entity
