// swiftlint:disable all
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen

{% if files %}
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
import Foundation

// swiftlint:disable superfluous_disable_command
// swiftlint:disable file_length

// MARK: - JSON Files
{% macro fileBlock file %}
  {% call documentBlock file file.document %}
{% endmacro %}
{% macro documentBlock file document %}
  {% set rootType %}{% call typeBlock document.metadata %}{% endset %}
  {% if document.metadata.type == "Array" %}
  {{accessModifier}} static let items: {{rootType}} = objectFromJSON(at: "{% call transformPath file.path %}")
  {% elif document.metadata.type == "Dictionary" %}
  private static let _document = JSONDocument(path: "{% call transformPath file.path %}")

  {% for key,value in document.metadata.properties %}
  {{accessModifier}} {% call propertyBlock key value %}
  {% endfor %}
  {% else %}
  {{accessModifier}} static let value: {{rootType}} = objectFromJSON(at: "{% call transformPath file.path %}")
  {% endif %}
{% endmacro %}
{% macro typeBlock metadata %}{% filter removeNewlines:"leading" %}
  {% if metadata.type == "Array" %}
    [{% call typeBlock metadata.element %}]
  {% elif metadata.type == "Dictionary" %}
    [String: Any]
  {% elif metadata.type == "Optional" %}
    Any?
  {% else %}
    {{metadata.type}}
  {% endif %}
{% endfilter %}{% endmacro %}
{% macro propertyBlock key metadata %}{% filter removeNewlines:"leading" %}
  {% set propertyName %}{{key|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}{% endset %}
  {% set propertyType %}{% call typeBlock metadata %}{% endset %}
  static let {{propertyName}}: {{propertyType}} = _document["{{key}}"]
{% endfilter %}{% endmacro %}
{% macro transformPath path %}{% filter removeNewlines %}
  {% if param.preservePath %}
    {{path}}
  {% else %}
    {{path|basename}}
  {% endif %}
{% endfilter %}{% endmacro %}

// swiftlint:disable identifier_name line_length type_body_length
{{accessModifier}} enum {{param.enumName|default:"JSONFiles"}} {
  {% if files.count > 1 or param.forceFileNameEnum %}
  {% for file in files %}
  {{accessModifier}} enum {{file.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
    {% filter indent:2 %}{% call fileBlock file %}{% endfilter %}
  }
  {% endfor %}
  {% else %}
  {% call fileBlock files.first %}
  {% endif %}
}
// swiftlint:enable identifier_name line_length type_body_length

// MARK: - Implementation Details

private func objectFromJSON<T>(at path: String) -> T {
  {% if param.lookupFunction %}
  guard let url = {{param.lookupFunction}}(path),
  {% else %}
  guard let url = {{param.bundle|default:"BundleToken.bundle"}}.url(forResource: path, withExtension: nil),
  {% endif %}
    let json = try? JSONSerialization.jsonObject(with: Data(contentsOf: url), options: []),
    let result = json as? T else {
    fatalError("Unable to load JSON at path: \(path)")
  }
  return result
}

private struct JSONDocument {
  let data: [String: Any]

  init(path: String) {
    self.data = objectFromJSON(at: path)
  }

  subscript<T>(key: String) -> T {
    guard let result = data[key] as? T else {
      fatalError("Property '\(key)' is not of type \(T.self)")
    }
    return result
  }
}
{% if not param.bundle and not param.lookupFunction %}

// swiftlint:disable convenience_type
private final class BundleToken {
  static let bundle: Bundle = {
    #if SWIFT_PACKAGE
    return Bundle.module
    #else
    return Bundle(for: BundleToken.self)
    #endif
  }()
}
// swiftlint:enable convenience_type
{% endif %}
{% else %}
// No files found
{% endif %}
