require './spec/spec_helper'

describe NumbersInWords do
  describe ".language" do
    after do
      NumbersInWords.instance_variable_set(:"@language", nil)
    end

    it "has a default value" do
      expect(NumbersInWords.language).to eq "English"
    end

    it "can be set" do
      NumbersInWords.language = "some language"
      expect(NumbersInWords.language).to eq "some language"
    end
  end

  describe ".in_words" do
    it do
      expect(NumbersInWords.in_words(100)).to eq "one hundred"
    end
  end

  describe ".in_numbers" do
    it do
      expect(NumbersInWords.in_numbers("one hundred")).to eq 100
    end
  end

  it "should print the digits 0-9 correctly" do
    numbers = %w[zero one two three four five six seven eight nine]

    10.times { |i| expect(i.in_words).to eq(numbers[i]) }
  end

  it "should print the digits 11-19 correctly" do
    words = %w[eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]
    numbers = [11,12,13,14,15,16,17,18,19]
    numbers.each_with_index do |number, index|
      expect(number.in_words).to eq(words[index])

    end
  end

  it "should handle two digit numbers" do
    expect(21.in_words). to eq("twenty one")
  end

  it "should handle three digit numbers" do
    expect(113.in_words). to eq("one hundred and thirteen")
    expect(299.in_words). to eq("two hundred and ninety nine")
    expect(300.in_words). to eq("three hundred")
    expect(101.in_words). to eq("one hundred and one")
  end

  it "should print out some random examples correctly" do
    expect(2999     .in_words). to eq("two thousand nine hundred and ninety nine")
    expect(99999    .in_words). to eq("ninety nine thousand nine hundred and ninety nine")
    expect(999999   .in_words). to eq("nine hundred and ninety nine thousand nine hundred and ninety nine")
    expect(123456   .in_words). to eq("one hundred and twenty three thousand four hundred and fifty six")
    expect(17054    .in_words). to eq("seventeen thousand and fifty four")
    expect(11004    .in_words). to eq("eleven thousand and four")
    expect(470154   .in_words). to eq("four hundred and seventy thousand one hundred and fifty four")
    expect(417155   .in_words). to eq("four hundred and seventeen thousand one hundred and fifty five")
    expect(999999   .in_words). to eq("nine hundred and ninety nine thousand nine hundred and ninety nine")
    expect(1000000  .in_words). to eq("one million")
    expect(1000001  .in_words). to eq("one million and one")
    expect(112      .in_words). to eq("one hundred and twelve")
  end

  it "should handle edge cases" do
    expect(1000001                 .in_words). to eq("one million and one")
    expect((10*10**12 + 10**6 +1)  .in_words). to eq("ten trillion one million and one")
    expect((10**75)                .in_words). to eq("one quattuorvigintillion")
    expect(10001001                .in_words). to eq("ten million one thousand and one")
  end

  it "should handle a googol and larger" do
    n=10**100
    expect((10**100 + 1)          .in_words). to eq("one googol and one")
    expect((42*10**100 + 16777216).in_words). to eq("forty two googol sixteen million seven hundred and seventy seven thousand two hundred and sixteen")
    expect((42* 10**100 * 10**100).in_words). to eq("forty two googol googol")
  end

  it "should handle negative numbers" do
    expect(-1            .in_words).to eq("minus one")
    expect(-9            .in_words).to eq("minus nine")
    expect(-10           .in_words).to eq("minus ten")
    expect(-15           .in_words).to eq("minus fifteen")
    expect(-100          .in_words).to eq("minus one hundred")
    expect((-1*(10**100)).in_words).to eq("minus one googol")
    expect(-123456789    .in_words).to eq("minus one hundred and twenty three million four hundred and fifty six thousand seven hundred and eighty nine")
  end

  it "should handle decimals" do
    #because of lack of absolute accuracy with floats
    #the output won't be exactly as you might expect
    #so we will match rather than find equivalents
    expect(1.1          .in_words).to match(/one point one/)
    expect(1.2345678    .in_words).to match(/one point two three four five six seven eight/)
    expect(1000.2345678 .in_words).to match(/one thousand point two three four five six seven eight/)
    expect(12345.2345678.in_words).to match(/twelve thousand three hundred and forty five point two three four five six seven eight/)
    expect((10**9 + 0.1).in_words).to match(/one billion point one/)
  end
end
