   Converts a JSON Schema to Xema source.
   """
 
-  alias Xema.Schema
+  @type json_schema :: true | false | map
+  @schema ~w(
+    additional_items
+    additional_properties
+    property_names
+    not
+    if
+    then
+    else
+    contains
+    items
+  )a
 
-  @type json_schema :: true | false | map
+  @schemas ~w(
+    all_of
+    any_of
+    one_of
+    items
+  )a
+
+  @schema_map ~w(
+    definitions
+    dependencies
+    pattern_properties
+    properties
+  )a
 
   @spec to_xema(json_schema :: json_schema) :: atom | tuple
   def to_xema(json) when is_map(json) do

      true -> type
      false -> {type, schema(json)}
    end
  end

  defp type(map) do
    {type, map} = Map.pop(map, "type", :any)
    {type_to_atom(type), map}
  end

  defp type_to_atom("object"), do: :map

  defp type_to_atom(type), do: String.to_existing_atom(type)

  defp schema(json), do: json |> Enum.map(&rule/1) |> Keyword.new()


    |> rule(value)
  end

  defp rule(:"$ref", value), do: {:ref, value}

  defp rule(:format, value) do
    {:format, value |> ConvCase.to_snake_case() |> String.to_existing_atom()}
  end

  defp rule(key, value) when key in @schema_map do
    {key, Enum.into(value, %{}, fn {key, value} -> {key, to_xema(value)} end)}
  end

  defp rule(key, value) when key in @schemas and is_list(value) do
    {key, Enum.map(value, &to_xema/1)}
  end

  defp rule(key, value) when key in @schema do
    {key, to_xema(value)}
  end

  defp rule(key, value), do: {key, value}
