=begin
#Lob

#The Lob API is organized around REST. Our API is designed to have predictable, resource-oriented URLs and uses HTTP response codes to indicate any API errors. <p> Looking for our [previous documentation](https://lob.github.io/legacy-docs/)? 

The version of the OpenAPI document: 1.3.0
Contact: lob-openapi@lob.com
Generated by: https://openapi-generator.tech
OpenAPI Generator version: 5.2.1

=end

require 'date'
require 'time'

module Lob
  class Letter
    attr_accessor :to

    attr_accessor :from

    attr_accessor :carrier

    attr_accessor :thumbnails

    # A date in YYYY-MM-DD format of the mailpiece's expected delivery date based on its `send_date`.
    attr_accessor :expected_delivery_date

    # A timestamp in ISO 8601 format of the date the resource was created.
    attr_accessor :date_created

    # A timestamp in ISO 8601 format of the date the resource was last modified.
    attr_accessor :date_modified

    # Only returned if the resource has been successfully deleted.
    attr_accessor :deleted

    # Unique identifier prefixed with `ltr_`.
    attr_accessor :id

    # Unique identifier prefixed with `tmpl_`. ID of a saved [HTML template](#section/HTML-Templates).
    attr_accessor :template_id

    # Unique identifier prefixed with `vrsn_`.
    attr_accessor :template_version_id

    # A [signed link](#section/Asset-URLs) served over HTTPS. The link returned will expire in 30 days to prevent mis-sharing. Each time a GET request is initiated, a new signed URL will be generated.
    attr_accessor :url

    attr_accessor :object

    # An internal description that identifies this resource. Must be no longer than 255 characters. 
    attr_accessor :description

    # Use metadata to store custom information for tagging and labeling back to your internal systems. Must be an object with up to 20 key-value pairs. Keys must be at most 40 characters and values must be at most 500 characters. Neither can contain the characters `\"` and `\\`. i.e. '{\"customer_id\" : \"NEWYORK2015\"}' Nested objects are not supported.  See [Metadata](#section/Metadata) for more information.
    attr_accessor :metadata

    # You can input a merge variable payload object to your template to render dynamic content. For example, if you have a template like: `{{variable_name}}`, pass in `{\"variable_name\": \"Harry\"}` to render `Harry`. `merge_variables` must be an object. Any type of value is accepted as long as the object is valid JSON; you can use `strings`, `numbers`, `booleans`, `arrays`, `objects`, or `null`. The max length of the object is 25,000 characters. If you call `JSON.stringify` on your object, it can be no longer than 25,000 characters. Your variable names cannot contain any whitespace or any of the following special characters: `!`, `\"`, `#`, `%`, `&`, `'`, `(`, `)`, `*`, `+`, `,`, `/`, `;`, `<`, `=`, `>`, `@`, `[`, `\\`, `]`, `^`, `` ` ``, `{`, `|`, `}`, `~`. More instructions can be found in [our guide to using html and merge variables](https://lob.com/resources/guides/general/using-html-and-merge-variables). Depending on your [Merge Variable strictness](https://dashboard.lob.com/#/settings/account) setting, if you define variables in your HTML but do not pass them here, you will either receive an error or the variable will render as an empty string.
    attr_accessor :merge_variables

    # A timestamp in ISO 8601 format which specifies a date after the current time and up to 180 days in the future to send the letter off for production. Setting a send date overrides the default [cancellation window](#section/Cancellation-Windows) applied to the mailpiece. Until the `send_date` has passed, the mailpiece can be canceled. If a date in the format `2017-11-01` is passed, it will evaluate to midnight UTC of that date (`2017-11-01T00:00:00.000Z`). If a datetime is passed, that exact time will be used. A `send_date` passed with no time zone will default to UTC, while a `send_date` passed with a time zone will be converted to UTC.
    attr_accessor :send_date

    # Add an extra service to your letter. See [pricing](https://www.lob.com/pricing/print-mail#compare) for extra costs incurred.
    attr_accessor :extra_service

    # The tracking number, if applicable, will appear here when it becomes available. Dummy tracking numbers are not created in test mode.
    attr_accessor :tracking_number

    # An array of tracking_event objects ordered by ascending `time`. Will not be populated for letters created in test mode.
    attr_accessor :tracking_events

    # Specifies the address the return envelope will be sent back to. This is an optional argument that is available if an account is signed up for the return envelope tracking beta, and has `return_envelope`, and `perforated_page` fields populated in the API request.
    attr_accessor :return_address

    attr_accessor :mail_type

    # Set this key to `true` if you would like to print in color. Set to `false` if you would like to print in black and white.
    attr_accessor :color

    # Set this attribute to `true` for double sided printing, or `false` for for single sided printing. Defaults to `true`.
    attr_accessor :double_sided

    # Specifies the location of the address information that will show through the double-window envelope. 
    attr_accessor :address_placement

    attr_accessor :return_envelope

    # Required if `return_envelope` is `true`. The number of the page that should be perforated for use with the return envelope. Must be greater than or equal to `1`. The blank page added by `address_placement=insert_blank_page` will be ignored when considering the perforated page number. To see how perforation will impact your letter design, view our [perforation guide](https://s3-us-west-2.amazonaws.com/public.lob.com/assets/templates/letter_perf_template.pdf).
    attr_accessor :perforated_page

    attr_accessor :custom_envelope

    # The unique ID of the associated campaign if the resource was generated from a campaign.
    attr_accessor :campaign_id

    attr_accessor :use_type

    class EnumAttributeValidator
      attr_reader :datatype
      attr_reader :allowable_values

      def initialize(datatype, allowable_values)
        @allowable_values = allowable_values.map do |value|
          case datatype.to_s
          when /Integer/i
            value.to_i
          when /Float/i
            value.to_f
          else
            value
          end
        end
      end

      def valid?(value)
        !value || allowable_values.include?(value)
      end
    end

    # Attribute mapping from ruby-style variable name to JSON key.
    def self.attribute_map
      {
        :'to' => :'to',
        :'from' => :'from',
        :'carrier' => :'carrier',
        :'thumbnails' => :'thumbnails',
        :'expected_delivery_date' => :'expected_delivery_date',
        :'date_created' => :'date_created',
        :'date_modified' => :'date_modified',
        :'deleted' => :'deleted',
        :'id' => :'id',
        :'template_id' => :'template_id',
        :'template_version_id' => :'template_version_id',
        :'url' => :'url',
        :'object' => :'object',
        :'description' => :'description',
        :'metadata' => :'metadata',
        :'merge_variables' => :'merge_variables',
        :'send_date' => :'send_date',
        :'extra_service' => :'extra_service',
        :'tracking_number' => :'tracking_number',
        :'tracking_events' => :'tracking_events',
        :'return_address' => :'return_address',
        :'mail_type' => :'mail_type',
        :'color' => :'color',
        :'double_sided' => :'double_sided',
        :'address_placement' => :'address_placement',
        :'return_envelope' => :'return_envelope',
        :'perforated_page' => :'perforated_page',
        :'custom_envelope' => :'custom_envelope',
        :'campaign_id' => :'campaign_id',
        :'use_type' => :'use_type'
      }
    end

    # Returns all the JSON keys this model knows about
    def self.acceptable_attributes
      attribute_map.values
    end

    # Attribute type mapping.
    def self.openapi_types
      {
        :'to' => :'Address',
        :'from' => :'Address',
        :'carrier' => :'String',
        :'thumbnails' => :'Array<Thumbnail>',
        :'expected_delivery_date' => :'Date',
        :'date_created' => :'Time',
        :'date_modified' => :'Time',
        :'deleted' => :'Boolean',
        :'id' => :'String',
        :'template_id' => :'String',
        :'template_version_id' => :'String',
        :'url' => :'String',
        :'object' => :'String',
        :'description' => :'String',
        :'metadata' => :'Hash<String, String>',
        :'merge_variables' => :'Object',
        :'send_date' => :'Time',
        :'extra_service' => :'String',
        :'tracking_number' => :'String',
        :'tracking_events' => :'Array<TrackingEventNormal>',
        :'return_address' => Array[:'AddressEditable', :'String'],
        :'mail_type' => :'MailType',
        :'color' => :'Boolean',
        :'double_sided' => :'Boolean',
        :'address_placement' => :'String',
        :'return_envelope' => Array[:'ReturnEnvelope', :'Boolean'],
        :'perforated_page' => :'Integer',
        :'custom_envelope' => :'LetterCustomEnvelope',
        :'campaign_id' => :'String',
        :'use_type' => :'LtrUseType'
      }
    end

    # List of attributes with nullable: true
    def self.openapi_nullable
      Set.new([
        :'description',
        :'merge_variables',
        :'tracking_number',
        :'return_address',
        :'return_envelope',
        :'perforated_page',
        :'custom_envelope',
        :'campaign_id',
        :'use_type'
      ])
    end

    # Initializes the object
    # @param [Hash] attributes Model attributes in the form of hash
    def initialize(attributes = {})
      if (!attributes.is_a?(Hash))
        fail ArgumentError, "The input argument (attributes) must be a hash in `Lob::Letter` initialize method"
      end

      # check to see if the attribute exists and convert string to symbol for hash key
      attributes = attributes.each_with_object({}) { |(k, v), h|
        if (!self.class.attribute_map.key?(k.to_sym))
          fail ArgumentError, "`#{k}` is not a valid attribute in `Lob::Letter`. Please check the name to make sure it's valid. List of attributes: " + self.class.attribute_map.keys.inspect
        end
        h[k.to_sym] = v
      }

      if attributes.key?(:'to')
        self.to = attributes[:'to']
      end

      if attributes.key?(:'from')
        self.from = attributes[:'from']
      end

      if attributes.key?(:'carrier')
        self.carrier = attributes[:'carrier']
      else
        self.carrier = 'USPS'
      end

      if attributes.key?(:'thumbnails')
        if (value = attributes[:'thumbnails']).is_a?(Array)
          self.thumbnails = value
        end
      end

      if attributes.key?(:'expected_delivery_date')
        self.expected_delivery_date = attributes[:'expected_delivery_date']
      end

      if attributes.key?(:'date_created')
        self.date_created = attributes[:'date_created']
      end

      if attributes.key?(:'date_modified')
        self.date_modified = attributes[:'date_modified']
      end

      if attributes.key?(:'deleted')
        self.deleted = attributes[:'deleted']
      end

      if attributes.key?(:'id')
        self.id = attributes[:'id']
      end

      if attributes.key?(:'template_id')
        self.template_id = attributes[:'template_id']
      end

      if attributes.key?(:'template_version_id')
        self.template_version_id = attributes[:'template_version_id']
      end

      if attributes.key?(:'url')
        self.url = attributes[:'url']
      end

      if attributes.key?(:'object')
        self.object = attributes[:'object']
      else
        self.object = 'letter'
      end

      if attributes.key?(:'description')
        self.description = attributes[:'description']
      end

      if attributes.key?(:'metadata')
        if (value = attributes[:'metadata']).is_a?(Hash)
          self.metadata = value
        end
      end

      if attributes.key?(:'merge_variables')
        self.merge_variables = attributes[:'merge_variables']
      end

      if attributes.key?(:'send_date')
        self.send_date = attributes[:'send_date']
      end

      if attributes.key?(:'extra_service')
        self.extra_service = attributes[:'extra_service']
      end

      if attributes.key?(:'tracking_number')
        self.tracking_number = attributes[:'tracking_number']
      end

      if attributes.key?(:'tracking_events')
        if (value = attributes[:'tracking_events']).is_a?(Array)
          self.tracking_events = value
        end
      end

      if attributes.key?(:'return_address')
        self.return_address = attributes[:'return_address']
      end

      if attributes.key?(:'mail_type')
        self.mail_type = attributes[:'mail_type']
      else
        self.mail_type = 'usps_first_class'
      end

      if attributes.key?(:'color')
        self.color = attributes[:'color']
      end

      if attributes.key?(:'double_sided')
        self.double_sided = attributes[:'double_sided']
      else
        self.double_sided = true
      end

      if attributes.key?(:'address_placement')
        self.address_placement = attributes[:'address_placement']
      else
        self.address_placement = 'top_first_page'
      end

      if attributes.key?(:'return_envelope')
        self.return_envelope = attributes[:'return_envelope']
      end

      if attributes.key?(:'perforated_page')
        self.perforated_page = attributes[:'perforated_page']
      end

      if attributes.key?(:'custom_envelope')
        self.custom_envelope = attributes[:'custom_envelope']
      end

      if attributes.key?(:'campaign_id')
        self.campaign_id = attributes[:'campaign_id']
      end

      if attributes.key?(:'use_type')
        self.use_type = attributes[:'use_type']
      end
    end

    # Show invalid properties with the reasons. Usually used together with valid?
    # @return Array for valid properties with the reasons
    def list_invalid_properties
      invalid_properties = Array.new
      if @to.nil?
        invalid_properties.push('invalid value for "to", to cannot be nil.')
      end

      if @from.nil?
        invalid_properties.push('invalid value for "from", from cannot be nil.')
      end

      if @date_created.nil?
        invalid_properties.push('invalid value for "date_created", date_created cannot be nil.')
      end

      if @date_modified.nil?
        invalid_properties.push('invalid value for "date_modified", date_modified cannot be nil.')
      end

      if @id.nil?
        invalid_properties.push('invalid value for "id", id cannot be nil.')
      end

      pattern = Regexp.new(/^ltr_[a-zA-Z0-9]+$/)
      if @id !~ pattern
        invalid_properties.push("invalid value for \"id\", must conform to the pattern #{pattern}.")
      end

      pattern = Regexp.new(/^tmpl_[a-zA-Z0-9]+$/)
      if !@template_id.nil? && @template_id !~ pattern
        invalid_properties.push("invalid value for \"template_id\", must conform to the pattern #{pattern}.")
      end

      pattern = Regexp.new(/^vrsn_[a-zA-Z0-9]+$/)
      if !@template_version_id.nil? && @template_version_id !~ pattern
        invalid_properties.push("invalid value for \"template_version_id\", must conform to the pattern #{pattern}.")
      end

      pattern = Regexp.new(/^https:\/\/lob-assets.com\/(letters|postcards|bank-accounts|checks|self-mailers|cards)\/[a-z]{3,4}_[a-z0-9]{15,16}(_signature)?(\.pdf|_thumb_[a-z]+_[0-9]+\.png|\.png)\?(version=[a-z0-9]*&)expires=[0-9]{10}&signature=[a-zA-Z0-9_-]+/)
      if !@url.nil? && @url !~ pattern
        invalid_properties.push("invalid value for \"url\", must conform to the pattern #{pattern}.")
      end

      if @object.nil?
        invalid_properties.push('invalid value for "object", object cannot be nil.')
      end

      if !@description.nil? && @description.to_s.length > 255
        invalid_properties.push('invalid value for "description", the character length must be smaller than or equal to 255.')
      end

      invalid_properties
    end

    # Check to see if the all the properties in the model are valid
    # @return true if the model is valid
    def valid?
      return false if @to.nil?
      return false if @from.nil?
      carrier_validator = EnumAttributeValidator.new('String', ["USPS"])
      return false unless carrier_validator.valid?(@carrier)
      return false if @date_created.nil?
      return false if @date_modified.nil?
      return false if @id.nil?
      return false if @id !~ Regexp.new(/^ltr_[a-zA-Z0-9]+$/)
      return false if !@template_id.nil? && @template_id !~ Regexp.new(/^tmpl_[a-zA-Z0-9]+$/)
      return false if !@template_version_id.nil? && @template_version_id !~ Regexp.new(/^vrsn_[a-zA-Z0-9]+$/)
      return false if !@url.nil? && @url !~ Regexp.new(/^https:\/\/lob-assets.com\/(letters|postcards|bank-accounts|checks|self-mailers|cards)\/[a-z]{3,4}_[a-z0-9]{15,16}(_signature)?(\.pdf|_thumb_[a-z]+_[0-9]+\.png|\.png)\?(version=[a-z0-9]*&)expires=[0-9]{10}&signature=[a-zA-Z0-9_-]+/)
      return false if @object.nil?
      object_validator = EnumAttributeValidator.new('String', ["letter"])
      return false unless object_validator.valid?(@object)
      return false if !@description.nil? && @description.to_s.length > 255
      address_placement_validator = EnumAttributeValidator.new('String', ["top_first_page", "insert_blank_page", "bottom_first_page_center", "bottom_first_page"])
      return false unless address_placement_validator.valid?(@address_placement)
      true
    end

    # Custom attribute writer method checking allowed values (enum).
    # @param [Object] carrier Object to be assigned
    def carrier=(carrier)
      validator = EnumAttributeValidator.new('String', ["USPS"])
      unless validator.valid?(carrier)
        fail ArgumentError, "invalid value for \"carrier\", must be one of #{validator.allowable_values}."
      end
      @carrier = carrier
    end

    # Custom attribute writer method with validation
    # @param [Object] id Value to be assigned
    def id=(id)
      if id.nil?
        fail ArgumentError, 'id cannot be nil'
      end

      pattern = Regexp.new(/^ltr_[a-zA-Z0-9]+$/)
      if id !~ pattern
        fail ArgumentError, "invalid value for \"id\", must conform to the pattern #{pattern}."
      end

      @id = id
    end

    # Custom attribute writer method with validation
    # @param [Object] template_id Value to be assigned
    def template_id=(template_id)
      pattern = Regexp.new(/^tmpl_[a-zA-Z0-9]+$/)
      if !template_id.nil? && template_id !~ pattern
        fail ArgumentError, "invalid value for \"template_id\", must conform to the pattern #{pattern}."
      end

      @template_id = template_id
    end

    # Custom attribute writer method with validation
    # @param [Object] template_version_id Value to be assigned
    def template_version_id=(template_version_id)
      pattern = Regexp.new(/^vrsn_[a-zA-Z0-9]+$/)
      if !template_version_id.nil? && template_version_id !~ pattern
        fail ArgumentError, "invalid value for \"template_version_id\", must conform to the pattern #{pattern}."
      end

      @template_version_id = template_version_id
    end

    # Custom attribute writer method with validation
    # @param [Object] url Value to be assigned
    def url=(url)
      pattern = Regexp.new(/^https:\/\/lob-assets.com\/(letters|postcards|bank-accounts|checks|self-mailers|cards)\/[a-z]{3,4}_[a-z0-9]{15,16}(_signature)?(\.pdf|_thumb_[a-z]+_[0-9]+\.png|\.png)\?(version=[a-z0-9]*&)expires=[0-9]{10}&signature=[a-zA-Z0-9_-]+/)
      if !url.nil? && url !~ pattern
        fail ArgumentError, "invalid value for \"url\", must conform to the pattern #{pattern}."
      end

      @url = url
    end

    # Custom attribute writer method checking allowed values (enum).
    # @param [Object] object Object to be assigned
    def object=(object)
      validator = EnumAttributeValidator.new('String', ["letter"])
      unless validator.valid?(object)
        fail ArgumentError, "invalid value for \"object\", must be one of #{validator.allowable_values}."
      end
      @object = object
    end

    # Custom attribute writer method with validation
    # @param [Object] description Value to be assigned
    def description=(description)
      if !description.nil? && description.to_s.length > 255
        fail ArgumentError, 'invalid value for "description", the character length must be smaller than or equal to 255.'
      end

      @description = description
    end

    # Custom attribute writer method with validation
    # @param [Object] metadata Value to be assigned
    def metadata=(metadata)
      @metadata = metadata
    end

    # Custom attribute writer method with validation
    # @param [Object] merge_variables Value to be assigned
    def merge_variables=(merge_variables)
      @merge_variables = merge_variables
    end

    # Custom attribute writer method checking allowed values (enum).
    # @param [Object] address_placement Object to be assigned
    def address_placement=(address_placement)
      validator = EnumAttributeValidator.new('String', ["top_first_page", "insert_blank_page", "bottom_first_page_center", "bottom_first_page"])
      unless validator.valid?(address_placement)
        fail ArgumentError, "invalid value for \"address_placement\", must be one of #{validator.allowable_values}."
      end
      @address_placement = address_placement
    end

    # Checks equality by comparing each attribute.
    # @param [Object] Object to be compared
    def ==(o)
      return true if self.equal?(o)
      self.class == o.class &&
          to == o.to &&
          from == o.from &&
          carrier == o.carrier &&
          thumbnails == o.thumbnails &&
          expected_delivery_date == o.expected_delivery_date &&
          date_created == o.date_created &&
          date_modified == o.date_modified &&
          deleted == o.deleted &&
          id == o.id &&
          template_id == o.template_id &&
          template_version_id == o.template_version_id &&
          url == o.url &&
          object == o.object &&
          description == o.description &&
          metadata == o.metadata &&
          merge_variables == o.merge_variables &&
          send_date == o.send_date &&
          extra_service == o.extra_service &&
          tracking_number == o.tracking_number &&
          tracking_events == o.tracking_events &&
          return_address == o.return_address &&
          mail_type == o.mail_type &&
          color == o.color &&
          double_sided == o.double_sided &&
          address_placement == o.address_placement &&
          return_envelope == o.return_envelope &&
          perforated_page == o.perforated_page &&
          custom_envelope == o.custom_envelope &&
          campaign_id == o.campaign_id &&
          use_type == o.use_type
    end

    # @see the `==` method
    # @param [Object] Object to be compared
    def eql?(o)
      self == o
    end

    # Calculates hash code according to all attributes.
    # @return [Integer] Hash code
    def hash
      [to, from, carrier, thumbnails, expected_delivery_date, date_created, date_modified, deleted, id, template_id, template_version_id, url, object, description, metadata, merge_variables, send_date, extra_service, tracking_number, tracking_events, return_address, mail_type, color, double_sided, address_placement, return_envelope, perforated_page, custom_envelope, campaign_id, use_type].hash
    end


    # Builds the object from hash
    # @param [Hash] attributes Model attributes in the form of hash
    # @return [Object] Returns the model itself
    def self.build_from_hash(attributes)
      new.build_from_hash(attributes)
    end

    # Builds the object from hash
    # @param [Hash] attributes Model attributes in the form of hash
    # @return [Object] Returns the model itself
    def build_from_hash(attributes)
      return nil unless attributes.is_a?(Hash)
      attributes = attributes.transform_keys(&:to_sym)
      self.class.openapi_types.each_pair do |key, type|
        if attributes[self.class.attribute_map[key]].nil? && self.class.openapi_nullable.include?(key)
          self.send("#{key}=", nil) # // guardrails-disable-line
        elsif type =~ /\AArray<(.*)>/i
          # check to ensure the input is an array given that the attribute
          # is documented as an array but the input is not
          if attributes[self.class.attribute_map[key]].is_a?(Array)
            self.send("#{key}=", attributes[self.class.attribute_map[key]].map { |v| _deserialize($1, v) }) # // guardrails-disable-line
          end
        elsif !attributes[self.class.attribute_map[key]].nil? && type.kind_of?(Array)
          for base_type in type do
            res = _deserialize(base_type, attributes[self.class.attribute_map[key]])
            if !res.nil?
              self.send("#{key}=", res) # // guardrails-disable-line
              break
            end
          end
        elsif !attributes[self.class.attribute_map[key]].nil?
          self.send("#{key}=", _deserialize(type, attributes[self.class.attribute_map[key]])) # // guardrails-disable-line
        end
      end

      self
    end

    # Deserializes the data based on type
    # @param string type Data type
    # @param string value Value to be deserialized
    # @return [Object] Deserialized data
    def _deserialize(type, value)
      case type.to_sym
      when :Time
        Time.parse(value)
      when :Date
        Date.parse(value)
      when :String
        value.to_s
      when :Integer
        value.to_i
      when :Float
        value.to_f
      when :Boolean
        if value.to_s =~ /\A(true|t|yes|y|1)\z/i
          true
        else
          false
        end
      when :Object
        # generic object (usually a Hash), return directly
        value
      when /\AArray<(?<inner_type>.+)>\z/
        inner_type = Regexp.last_match[:inner_type]
        value.map { |v| _deserialize(inner_type, v) }
      when /\AHash<(?<k_type>.+?), (?<v_type>.+)>\z/
        k_type = Regexp.last_match[:k_type]
        v_type = Regexp.last_match[:v_type]
        {}.tap do |hash|
          value.each do |k, v|
            hash[_deserialize(k_type, k)] = _deserialize(v_type, v)
          end
        end
      else # model
        # models (e.g. Pet) or oneOf
        klass = Lob.const_get(type)
        klass.respond_to?(:openapi_one_of) ? klass.build(value) : klass.build_from_hash(value)
      end
    end

    # Returns the string representation of the object
    # @return [String] String presentation of the object
    def to_s
      to_hash.to_s
    end

    # to_body is an alias to to_hash (backward compatibility)
    # @return [Hash] Returns the object in the form of hash
    def to_body
      to_hash
    end

    # Returns the object in the form of hash
    # @return [Hash] Returns the object in the form of hash
    def to_hash
      hash = {}
      self.class.attribute_map.each_pair do |attr, param|
        value = self.send(attr) # // guardrails-disable-line
        if value.nil?
          is_nullable = self.class.openapi_nullable.include?(attr)
          next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
        end

        hash[param] = _to_hash(value)
      end
      hash
    end

    # Outputs non-array value in the form of hash
    # For object, use to_hash. Otherwise, just return the value
    # @param [Object] value Any valid value
    # @return [Hash] Returns the value in the form of hash
    def _to_hash(value)
      if value.is_a?(Array)
        value.compact.map { |v| _to_hash(v) }
      elsif value.is_a?(Hash)
        {}.tap do |hash|
          value.each { |k, v| hash[k] = _to_hash(v) }
        end
      elsif value.respond_to? :to_hash
        value.to_hash
      else
        value
      end
    end

  end

end
