# frozen_string_literal: true

require "mime/types"
require "minitest_helper"

describe MIME::Types, "registry" do
  def setup
    MIME::Types.send(:load_default_mime_types)
  end

  describe "is enumerable" do
    it "correctly uses an Enumerable method like #any?" do
      assert(MIME::Types.any? { |type| type.content_type == "text/plain" })
    end

    it "implements each with no parameters to return an Enumerator" do
      assert_kind_of Enumerator, MIME::Types.each
      assert_kind_of Enumerator, MIME::Types.map
    end

    it "will create a lazy enumerator" do
      assert_kind_of Enumerator::Lazy, MIME::Types.lazy
      assert_kind_of Enumerator::Lazy, MIME::Types.map.lazy
    end

    it "is countable with an enumerator" do
      assert MIME::Types.each.count > 999
      assert MIME::Types.lazy.count > 999
    end
  end

  describe ".[]" do
    it "can be searched with a MIME::Type" do
      text_plain = MIME::Type.new("content-type" => "text/plain")
      assert_includes MIME::Types[text_plain], "text/plain"
      assert_equal 1, MIME::Types[text_plain].size
    end

    it "can be searched with a regular expression" do
      assert_includes MIME::Types[/plain$/], "text/plain"
      assert_equal 1, MIME::Types[/plain$/].size
    end

    it "sorts by priority with multiple matches" do
      types = MIME::Types[/gzip$/].select { |t|
        %w[application/gzip application/x-gzip multipart/x-gzip].include?(t)
      }
      # This is this way because of a new type ending with gzip that only
      # appears in some data files.
      assert_equal %w[application/gzip multipart/x-gzip application/x-gzip], types
      assert_equal 3, types.size
    end

    it "can be searched with a string" do
      assert_includes MIME::Types["text/plain"], "text/plain"
      assert_equal 1, MIME::Types["text/plain"].size
    end

    it "can be searched with the complete flag" do
      assert_empty MIME::Types[
        "application/x-www-form-urlencoded",
        complete: true
      ]
      assert_includes MIME::Types["text/plain", complete: true], "text/plain"
      assert_equal 1, MIME::Types["text/plain", complete: true].size
    end

    it "can be searched with the registered flag" do
      assert_empty MIME::Types["application/x-wordperfect6.1", registered: true]
      refute_empty MIME::Types[
        "application/x-www-form-urlencoded",
        registered: true
      ]
      refute_empty MIME::Types[/gzip/, registered: true]
      refute_equal MIME::Types[/gzip/], MIME::Types[/gzip/, registered: true]
    end
  end

  describe ".type_for" do
    it "finds all types for a given extension" do
      assert_equal %w[application/gzip application/x-gzip],
        MIME::Types.type_for("gz")
    end

    it "separates the extension from filenames" do
      assert_equal %w[image/jpeg], MIME::Types.of(["foo.jpeg", "bar.jpeg"])
    end

    it "finds multiple extensions ordered by the filename list" do
      result = MIME::Types.type_for(%w[foo.txt foo.jpeg])

      # assert_equal %w[text/plain image/jpeg], MIME::Types.type_for(%w[foo.txt foo.jpeg])
      assert_equal %w[text/plain image/jpeg], result
    end

    it "does not find unknown extensions" do
      assert_empty MIME::Types.type_for("zzz")
    end

    it "modifying type extensions causes reindexing" do
      plain_text = MIME::Types["text/plain"].first
      plain_text.add_extensions("xtxt")
      assert_includes MIME::Types.type_for("xtxt"), "text/plain"
    end

    it "handles newline characters correctly" do
      assert_includes MIME::Types.type_for("test.pdf\n.txt"), "text/plain"
      assert_includes MIME::Types.type_for("test.txt\n.pdf"), "application/pdf"
    end

    it "returns a stable order for types with equal priority" do
      assert_equal %w[text/x-vcalendar text/x-vcard], MIME::Types[/text\/x-vca/]
    end
  end

  describe ".count" do
    it "can count the number of types inside" do
      assert MIME::Types.count > 999
    end
  end

  describe ".add" do
    def setup
      MIME::Types.instance_variable_set(:@__types__, nil)
      MIME::Types.send(:load_default_mime_types)
    end

    let(:eruby) { MIME::Type.new("content-type" => "application/x-eruby") }
    let(:jinja) { MIME::Type.new("content-type" => "application/jinja2") }

    it "successfully adds a new type" do
      MIME::Types.add(eruby)
      assert_equal MIME::Types["application/x-eruby"], [eruby]
    end

    it "complains about adding a duplicate type" do
      MIME::Types.add(eruby)
      assert_output "", /is already registered as a variant/ do
        MIME::Types.add(eruby)
      end
      assert_equal MIME::Types["application/x-eruby"], [eruby]
    end

    it "does not complain about adding a duplicate type when quiet" do
      MIME::Types.add(eruby)
      assert_silent do
        MIME::Types.add(eruby, :silent)
      end
      assert_equal MIME::Types["application/x-eruby"], [eruby]
    end

    it "successfully adds from an array" do
      MIME::Types.add([eruby, jinja])
      assert_equal MIME::Types["application/x-eruby"], [eruby]
      assert_equal MIME::Types["application/jinja2"], [jinja]
    end

    it "successfully adds from another MIME::Types" do
      old_count = MIME::Types.count

      mt = MIME::Types.new
      mt.add(eruby)

      MIME::Types.add(mt)
      assert_equal old_count + 1, MIME::Types.count

      assert_equal MIME::Types[eruby.content_type], [eruby]
    end
  end
end
