{% set namespace_class_name = fmt_class(namespace.name) %}
///
/// Copyright (c) 2022 Dropbox, Inc. All rights reserved.
///
/// Auto-generated by Stone, do not modify.
///

import Foundation
import SwiftyDropbox

/// Objective-C compatible datatypes for the {{ namespace.name }} namespace
/// For Swift see {{ namespace.name }}

{% for data_type in namespace.linearize_data_types() %}
{% set data_type_class_name = fmt_class(data_type.name) %}
{% set swift_var_name = objc_swift_var_name(data_type) %}
{% set swift_type = namespace_class_name + '.' + data_type_class_name %}
{{ data_objc_type_doc(data_type) }}
{% if is_struct_type(data_type) %}
@objc
public class DBX{{ namespace_class_name }}{{ data_type_class_name }}: {{ 'NSObject' if not data_type.parent_type else fmt_objc_type(data_type.parent_type) }} {
    {% for field in data_type.fields %}
    {{ struct_field_doc(field, '    ') }}
    @objc
    {% if field_datatype_has_subtypes(field) %}
    public var {{ fmt_var(field.name) }}: {{ fmt_objc_type(field.data_type) }} {
        {% if (field_is_user_defined(field)) or (field_is_user_defined_optional(field)) %}
        {% if field_is_user_defined_optional(field) %}
        return {{ swift_var_name }}.{{ fmt_var(field.name) }}.flatMap { {{ fmt_objc_type(field.data_type, False) }}.wrapPreservingSubtypes(swift: $0) }
        {% else %}
        return {{ fmt_objc_type(field.data_type) }}.wrapPreservingSubtypes(swift: {{ swift_var_name }}.{{ fmt_var(field.name) }})
        {% endif %}
        {% elif (field_is_user_defined_map(field)) or (field_is_user_defined_list(field)) %}
        {{ swift_var_name }}.{{ fmt_var(field.name) }}.{{ 'mapValues' if field_is_user_defined_map(field) else 'map' }} {
            return {{ fmt_objc_type(field.data_type.data_type) }}.wrapPreservingSubtypes(swift: $0)
        }
        {% endif %}
    }
    {% else %}
    public var {{ fmt_var(field.name) }}: {{ fmt_objc_type(field.data_type) }} { {{ objc_return_field_value_oneliner(data_type, field) }} }
    {% endif %}
    {% endfor %}
    {% if data_type.fields %}

    @objc
    public init({{ func_args(objc_init_args(data_type)) }}) {
        {% if data_type.parent_type %}
        let swift = {{ swift_type }}({{ objc_init_args_to_swift(data_type) }})
        self.{{ swift_var_name }} = swift
        super.init(swift: swift)
        {% else %}
        self.{{ swift_var_name }} = {{ swift_type }}({{ objc_init_args_to_swift(data_type) }})
        {% endif %}
    }
    {% endif %}

    let {{ swift_var_name }}: {{ swift_type }}

    public init(swift: {{ swift_type }}) {
        self.{{ swift_var_name }} = swift
        {% if data_type.parent_type %}
        super.init(swift: swift)
        {% endif %}
    }

    {% if objc_datatype_value_type_tuples(data_type)|length > 0 %}
    public static func wrapPreservingSubtypes(swift: {{ swift_type }}) -> DBX{{ namespace_class_name }}{{ data_type_class_name }} {
        switch swift {
        {% for tuple in objc_datatype_value_type_tuples(data_type) %}
        case let {{ tuple[0] }} as {{ tuple[1] }}:
            return {{ tuple[2] }}(swift: {{ tuple[0] }})
        {% endfor %}
        default:
            return DBX{{ namespace_class_name }}{{ data_type_class_name }}(swift: swift)
        }
    }
    {% endif %}

    @objc
    public override var description: String { {{ 'swift' if not data_type.parent_type else 'subSwift'  }}.description }
}

{% elif is_union_type(data_type) %}
{% set union_class_name = 'DBX' + namespace_class_name + data_type_class_name %}
{% set swift_enum = namespace_class_name + '.' + fmt_class(data_type.name) %}
@objc
public class {{ union_class_name }}: NSObject {
    let swift: {{ swift_enum }}

    public init(swift: {{ swift_enum }}) {
        self.swift = swift
    }

    public static func factory(swift: {{ swift_enum }}) -> {{ union_class_name }} {
        switch swift {
        {% for field in data_type.all_fields %}
        {% set field_class_name = fmt_class(field.name) %}
        {% set field_subclass = union_class_name + field_class_name %}
        {% set guard = union_swift_arg_guard(field, field_subclass) %}
        {% set tag_type = fmt_objc_type(field.data_type) %}
        case .{{ fmt_var(field.name) }}{{ '(let swiftArg)' if tag_type else '' }}:
            {% if tag_type %}
            {% if guard %}
            {{ guard }}
            {% endif %}
            let arg = {{ swift_union_arg_to_objc(field) }}
            {% endif %}
            return {{ field_subclass }}({{ 'arg' if tag_type else '' }})
        {% endfor %}
        }
    }

    @objc
    public override var description: String { swift.description }
    {% for field in data_type.all_fields %}
    {% set field_class_name = fmt_class(field.name) %}
    {% set field_subclass = union_class_name + field_class_name %}

    @objc
    public var as{{ field_class_name }}: {{ field_subclass }}? {
        return self as? {{ field_subclass }}
    }
    {% endfor %}
}

{% for field in data_type.all_fields %}
{% set field_class_name = fmt_class(field.name) %}
{% set field_var_name = fmt_var(field.name) %}
{% set swift_enum_case = swift_enum + '.' + field_var_name %}
{% set tag_type = fmt_objc_type(field.data_type) %}
{{ union_field_doc(field) }}
@objc
public class {{ union_class_name }}{{ field_class_name }}: {{ union_class_name }} {
    {% if tag_type %}
    @objc
    public var {{ field_var_name }}: {{ tag_type }}

    {% endif %}
    @objc
    public init({{ '_ arg: '+tag_type if tag_type else '' }}) {
        {% if tag_type %}
        {{ field_var_name }} = arg
        {% endif %}
        let swift = {{ swift_enum_case }}{{ objc_union_arg(field) }}
        super.init(swift: swift)
    }
}

{% endfor %}
{% endif %}
{% endfor %}

