module SlugHelpers
  # TODO: get lists dynamically
  AGENT_RECORD_TYPES = [
    "AgentPerson",
    "AgentFamily",
    "AgentCorporateEntity",
    "AgentSoftware",
  ].freeze

  BASE_RECORD_TYPES = [
    "Resource",
    "Subject",
    "DigitalObject",
    "Accession",
    "Classification",
    "ClassificationTerm",
    "ArchivalObject",
    "DigitalObjectComponent",
  ].freeze

  NAME_RECORD_TYPES = [
    "NamePerson",
    "NameCorporateEntity",
    "NameFamily",
    "NameSoftware",
  ].freeze

  def self.slug_record_types
    @@slug_record_types ||= (AGENT_RECORD_TYPES + BASE_RECORD_TYPES).map { |string| Kernel.const_get(string) }
  end

  # Determine if our record has updated a data field that indicates an autogenerated slug should be updated.
  # Generally, we'll always want to return true here and run the slug code if the record is brand new (hasn't been persisted)
  # slug will be updated iff this method returns true
  def self.slug_data_updated?(obj)
    id_field_changed   = false
    name_field_changed = false
    persisted          = obj.exists?

    slug_field_changed = obj.column_changed?(:slug)
    slug_auto_field_changed = obj.column_changed?(:is_slug_auto)

    updated = false

    case obj.class.to_s
    when "Resource"
      if AppConfig[:generate_resource_slugs_with_eadid]
        id_field_changed = obj.column_changed?(:ead_id)     || !persisted
      else
        id_field_changed = obj.column_changed?(:identifier) || !persisted
      end

      name_field_changed = obj.column_changed?(:title) || !persisted

    when "Accession"
      id_field_changed = obj.column_changed?(:identifier) || !persisted
      name_field_changed = obj.column_changed?(:title)    || !persisted

    when "DigitalObject"
      id_field_changed = obj.column_changed?(:digital_object_id) || !persisted
      name_field_changed = obj.column_changed?(:title)           || !persisted

    when "DigitalObjectComponent"
      id_field_changed = obj.column_changed?(:component_id) || !persisted
      name_field_changed = obj.column_changed?(:title)      || !persisted

    when "Classification"
      id_field_changed = obj.column_changed?(:identifier) || !persisted
      name_field_changed = obj.column_changed?(:title)    || !persisted

    when "ClassificationTerm"
      id_field_changed = obj.column_changed?(:identifier) || !persisted
      name_field_changed = obj.column_changed?(:title)    || !persisted

    when "Repository"
      id_field_changed = obj.column_changed?(:repo_code) || !persisted
      name_field_changed = obj.column_changed?(:name)    || !persisted

    when "ArchivalObject"
      if AppConfig[:generate_archival_object_slugs_with_cuid] = true
        id_field_changed = obj.column_changed?(:component_id) || !persisted
      else
        id_field_changed = obj.column_changed?(:ref_id) || !persisted
      end

      name_field_changed = obj.column_changed?(:title) || !persisted

    when "Subject"
      id_field_changed = obj.column_changed?(:authority_id) || !persisted
      name_field_changed = obj.column_changed?(:title) || !persisted
    end

    # for agent objects, the fields we need for name slugs are in a different table.
    # since we don't have access to that object here, we'll always process slugs for agents.
    # We only want to update the name agent classes if they exist already and have an ID. (persisted) This is because on create, the auto_generate hook on the Agent model creates a slug and we don't want a duplicate.

    # The only time we want to run slug code for agent classes is when the is_slug_auto flag is toggled
    if is_agent_type?(obj.class)
      id_field_changed = false
      name_field_changed = false
    end

    # only run slug code for this AgentName if it's a display name
    if is_agent_name_type?(obj.class)
      id_field_changed = false
      name_field_changed = obj[:is_display_name] == 1
    end


    # auto-gen slugs has been switched from OFF to ON
    if slug_auto_field_changed && obj[:is_slug_auto] == 1
      updated = true

    # auto-gen slugs is OFF, and slug field updated
    elsif obj[:is_slug_auto] == 0 && slug_field_changed
      updated = true

    # auto-gen slugs is ON based on name, and name has changed
    elsif !AppConfig[:auto_generate_slugs_with_id] && name_field_changed
      updated = true

    # auto-gen slugs is ON based on id, and id has changed
    elsif AppConfig[:auto_generate_slugs_with_id] && id_field_changed
      updated = true

    # any other case, we can skip slug processing
    else
      updated = false
    end

    return updated
  end

  # returns true if is_slug_auto is enabled for entity, or if we should treat it like it is
  def self.is_slug_auto_enabled?(entity)
    enabled = false

    if entity[:is_slug_auto] && entity[:is_slug_auto] == 1
      enabled = true

    # the agent Name classes don't have slug fields, but if they are being updated, we may need to update the associated agent.
    elsif is_agent_name_type?(entity.class)
      enabled = true
    end

    return enabled
  end

  def self.is_agent_name_type?(klass)
    NAME_RECORD_TYPES.include?(klass.to_s)
  end

  def self.is_agent_type?(klass)
    AGENT_RECORD_TYPES.include?(klass.to_s)
  end

  def self.base_sluggable_class?(klass)
    BASE_RECORD_TYPES.include?(klass.to_s)
  end
end
