class Avo::Fields::BelongsToField

def database_id

def database_id
  # If the field is a polymorphic value, return the polymorphic_type as key and pre-fill the _id in fill_field.
  return "#{polymorphic_as}_type" if polymorphic_as.present?
  foreign_key
rescue
  id
end

def database_value

def database_value
  target_resource.id
rescue
  nil
end

def field_label

What the user sees in the text field
def field_label
  label
end

def field_value

The value
def field_value
  value.send(database_value)
rescue
  nil
end

def fill_field(model, key, value, params)

def fill_field(model, key, value, params)
  return model unless model.methods.include? key.to_sym
  if polymorphic_as.present?
    valid_model_class = valid_polymorphic_class params["#{polymorphic_as}_type"]
    model.send("#{polymorphic_as}_type=", valid_model_class)
    # If the type is blank, reset the id too.
    if valid_model_class.blank?
      model.send("#{polymorphic_as}_id=", nil)
    else
      model.send("#{polymorphic_as}_id=", params["#{polymorphic_as}_id"])
    end
  else
    model.send("#{key}=", value)
  end
  model
end

def foreign_key

def foreign_key
  return polymorphic_as if polymorphic_as.present?
  if @record.present?
    get_model_class(@record).reflections[@relation_method].foreign_key
  elsif @resource.present? && @resource.model_class.reflections[@relation_method].present?
    @resource.model_class.reflections[@relation_method].foreign_key
  end
end

def get_model

def get_model
  return @record if @record.present?
  @resource.record
rescue
  nil
end

def get_model_class(model)

def get_model_class(model)
  if model.instance_of?(Class)
    model
  else
    model.class
  end
end

def id_input_foreign_key

def id_input_foreign_key
  if is_polymorphic?
    "#{foreign_key}_id"
  else
    foreign_key
  end
end

def initialize(id, **args, &block)

def initialize(id, **args, &block)
  args[:placeholder] ||= I18n.t("avo.choose_an_option")
  super(id, **args, &block)
  @searchable = args[:searchable] == true
  @polymorphic_as = args[:polymorphic_as]
  @types = args[:types]
  @relation_method = id.to_s.parameterize.underscore
  @allow_via_detaching = args[:allow_via_detaching] == true
  @attach_scope = args[:attach_scope]
  @polymorphic_help = args[:polymorphic_help]
  @target = args[:target]
  @use_resource = args[:use_resource] || nil
end

def is_polymorphic?

def is_polymorphic?
  polymorphic_as.present?
rescue
  false
end

def label

def label
  return if target_resource.blank?
  target_resource.new(record: value)&.record_title
end

def name

def name
  return polymorphic_as.to_s.humanize if polymorphic_as.present? && view == :index
  super
end

def options

def options
  values_for_type
end

def reflection

Get the model reflection instance
def reflection
  reflection_for_key(id)
rescue
  nil
end

def reflection_for_key(key)

def reflection_for_key(key)
  get_model_class(get_model).reflections[key.to_s]
rescue
  nil
end

def relation_model_class

def relation_model_class
  @resource.model_class
end

def target_resource

def target_resource
  return use_resource if use_resource.present?
  if is_polymorphic?
    if value.present?
      return Avo.resource_manager.get_resource_by_model_class(value.class)
    else
      return nil
    end
  end
  reflection_key = polymorphic_as || id
  if @record._reflections[reflection_key.to_s].klass.present?
    Avo.resource_manager.get_resource_by_model_class @record._reflections[reflection_key.to_s].klass.to_s
  elsif @record._reflections[reflection_key.to_s].options[:class_name].present?
    Avo.resource_manager.get_resource_by_model_class @record._reflections[reflection_key.to_s].options[:class_name]
  else
    App.get_resource_by_name reflection_key.to_s
  end
end

def to_permitted_param

def to_permitted_param
  if polymorphic_as.present?
    return ["#{polymorphic_as}_type".to_sym, "#{polymorphic_as}_id".to_sym]
  end
  foreign_key.to_sym
end

def type_input_foreign_key

def type_input_foreign_key
  if is_polymorphic?
    "#{foreign_key}_type"
  end
end

def valid_polymorphic_class(possible_class)

def valid_polymorphic_class(possible_class)
  types.find do |type|
    type.to_s == possible_class.to_s
  end
end

def value

def value
  if is_polymorphic?
    # Get the value from the pre-filled assoociation record
    super(polymorphic_as)
  else
    # Get the value from the pre-filled assoociation record
    super(relation_method)
  end
end

def values_for_type(model = nil)

def values_for_type(model = nil)
  resource = target_resource
  resource = Avo.resource_manager.get_resource_by_model_class model if model.present?
  query = resource.query_scope
  if attach_scope.present?
    query = Avo::ExecutionContext.new(target: attach_scope, query: query, parent: get_model).handle
  end
  query.all.map do |record|
    [resource.new(record: record).record_title, record.id]
  end
end