local decimal_fraction = require("dial.augend").decimal_fraction

describe("Test of decimal fraction { signed = false }", function()
    local augend = decimal_fraction.new { signed = false }

    describe("find function", function()
        it("can find a decimal fraction", function()
            assert.are.same(augend:find_stateful("273.15", 1), { from = 1, to = 6 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("0.0", 1), { from = 1, to = 3 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("123 273.15", 1), { from = 5, to = 10 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("foo 42.195 28.3 bar", 1), { from = 5, to = 10 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("foo 42.195 28.3 bar", 5), { from = 5, to = 10 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("foo 42.195 28.3 bar", 7), { from = 5, to = 10 })
            assert.are.same(augend.digits_to_add, 3)
            assert.are.same(augend:find_stateful("foo 42.195 28.3 bar", 10), { from = 5, to = 10 })
            assert.are.same(augend.digits_to_add, 3)
            assert.are.same(augend:find_stateful("foo 42.195 28.3 bar", 11), { from = 12, to = 15 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("foo 42.195 28.3 bar", 14), { from = 12, to = 15 })
            assert.are.same(augend.digits_to_add, 1)
            assert.are.same(augend:find_stateful("foo 42.195 28.3 bar", 16), nil)
        end)

        it("changes the value of digits_to_add appropriately depending on the cursor position", function()
            assert.are.same(augend:find_stateful("273.15", 1), { from = 1, to = 6 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("273.15", 3), { from = 1, to = 6 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("273.15", 4), { from = 1, to = 6 })
            assert.are.same(augend.digits_to_add, 2)
            assert.are.same(augend:find_stateful("273.15", 5), { from = 1, to = 6 })
            assert.are.same(augend.digits_to_add, 2)
            assert.are.same(augend:find_stateful("273.15", 6), { from = 1, to = 6 })
            assert.are.same(augend.digits_to_add, 2)

            assert.are.same(augend:find_stateful("9.80665", 1), { from = 1, to = 7 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("9.80665", 3), { from = 1, to = 7 })
            assert.are.same(augend.digits_to_add, 5)
            assert.are.same(augend:find_stateful("9.80665", 4), { from = 1, to = 7 })
            assert.are.same(augend.digits_to_add, 5)
            assert.are.same(augend:find_stateful("9.80665", 5), { from = 1, to = 7 })
            assert.are.same(augend.digits_to_add, 5)
            assert.are.same(augend:find_stateful("9.80665", 6), { from = 1, to = 7 })
            assert.are.same(augend.digits_to_add, 5)
        end)

        it("returns nil when no number appears", function()
            assert.are.same(augend:find("", 1), nil)
            assert.are.same(augend:find("foo bar", 1), nil)
        end)
        it("doesn't pick up negative number", function()
            assert.are.same(augend:find("-42.195", 1), { from = 2, to = 7 })
            assert.are.same(augend:find("fname-1.3", 1), { from = 7, to = 9 })
        end)
        it("doesn't pick up incomplete decimal fraction", function()
            assert.are.same(augend:find("-42.", 1), nil)
            assert.are.same(augend:find("fname-1.png", 1), nil)
            assert.are.same(augend:find(".1", 1), nil)
        end)
    end)

    describe("add function", function()
        it("can increment integer parts", function()
            augend.digits_to_add = 0
            assert.are.same(augend:add("273.15", 1, 1), { text = "274.15", cursor = 3 })
            assert.are.same(augend:add("273.15", 10, 1), { text = "283.15", cursor = 3 })
            assert.are.same(augend:add("273.15", 10, 4), { text = "283.15", cursor = 3 })
            assert.are.same(augend:add("273.15", 100, 1), { text = "373.15", cursor = 3 })
            assert.are.same(augend:add("273.15", 1000, 1), { text = "1273.15", cursor = 4 })
            assert.are.same(augend:add("273.15", -1, 1), { text = "272.15", cursor = 3 })
            assert.are.same(augend:add("273.15", -10, 1), { text = "263.15", cursor = 3 })
            assert.are.same(augend:add("273.15", -100, 1), { text = "173.15", cursor = 3 })
            assert.are.same(augend:add("273.15", -200, 1), { text = "73.15", cursor = 2 })
            assert.are.same(augend:add("273.15", -270, 1), { text = "3.15", cursor = 1 })
            assert.are.same(augend:add("273.15", -273, 1), { text = "0.15", cursor = 1 })
            assert.are.same(augend:add("273.15", -274, 1), { text = "0.00", cursor = 1 })
            assert.are.same(augend:add("273.15", -1000, 1), { text = "0.00", cursor = 1 })
        end)
        it("can increment fragment parts", function()
            augend.digits_to_add = 1
            assert.are.same(augend:add("273.15", 1, 1), { text = "273.25", cursor = 6 })
            assert.are.same(augend:add("273.15", 9, 1), { text = "274.05", cursor = 6 })
            assert.are.same(augend:add("273.15", 10, 1), { text = "274.15", cursor = 6 })
            assert.are.same(augend:add("273.15", 10, 4), { text = "274.15", cursor = 6 })
            assert.are.same(augend:add("273.15", 100, 1), { text = "283.15", cursor = 6 })
            assert.are.same(augend:add("273.15", 1000, 1), { text = "373.15", cursor = 6 })
            assert.are.same(augend:add("273.15", 10000, 1), { text = "1273.15", cursor = 7 })
            assert.are.same(augend:add("273.15", -1, 1), { text = "273.05", cursor = 6 })
            assert.are.same(augend:add("273.15", -2, 1), { text = "272.95", cursor = 6 })
            assert.are.same(augend:add("273.15", -10, 1), { text = "272.15", cursor = 6 })
            assert.are.same(augend:add("273.15", -100, 1), { text = "263.15", cursor = 6 })
            assert.are.same(augend:add("273.15", -1000, 1), { text = "173.15", cursor = 6 })
            assert.are.same(augend:add("273.15", -10000, 1), { text = "0.00", cursor = 4 })

            augend.digits_to_add = 2
            assert.are.same(augend:add("273.15", 1, 1), { text = "273.16", cursor = 6 })
            assert.are.same(augend:add("273.15", 5, 1), { text = "273.20", cursor = 6 })
            assert.are.same(augend:add("273.15", 10, 1), { text = "273.25", cursor = 6 })
            assert.are.same(augend:add("273.15", 90, 1), { text = "274.05", cursor = 6 })
            assert.are.same(augend:add("273.15", 1000, 1), { text = "283.15", cursor = 6 })

            augend.digits_to_add = 3
            assert.are.same(augend:add("273.15", 1, 1), { text = "273.151", cursor = 7 })
            assert.are.same(augend:add("273.15", 5, 1), { text = "273.155", cursor = 7 })
            assert.are.same(augend:add("273.15", 10, 1), { text = "273.160", cursor = 7 })
        end)
    end)
end)

describe("Test of decimal fraction { signed = true }", function()
    local augend = decimal_fraction.new { signed = true }

    describe("find function", function()
        it("can find a decimal fraction", function()
            assert.are.same(augend:find_stateful("273.15", 1), { from = 1, to = 6 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("0.0", 1), { from = 1, to = 3 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("123 273.15", 1), { from = 5, to = 10 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("foo 42.195 28.3 bar", 1), { from = 5, to = 10 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("foo 42.195 28.3 bar", 5), { from = 5, to = 10 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("foo 42.195 28.3 bar", 7), { from = 5, to = 10 })
            assert.are.same(augend.digits_to_add, 3)
            assert.are.same(augend:find_stateful("foo 42.195 28.3 bar", 10), { from = 5, to = 10 })
            assert.are.same(augend.digits_to_add, 3)
            assert.are.same(augend:find_stateful("foo 42.195 28.3 bar", 11), { from = 12, to = 15 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("foo 42.195 28.3 bar", 14), { from = 12, to = 15 })
            assert.are.same(augend.digits_to_add, 1)
            assert.are.same(augend:find_stateful("foo 42.195 28.3 bar", 16), nil)
        end)

        it("changes the value of digits_to_add appropriately depending on the cursor position", function()
            assert.are.same(augend:find_stateful("273.15", 1), { from = 1, to = 6 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("273.15", 3), { from = 1, to = 6 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("273.15", 4), { from = 1, to = 6 })
            assert.are.same(augend.digits_to_add, 2)
            assert.are.same(augend:find_stateful("273.15", 5), { from = 1, to = 6 })
            assert.are.same(augend.digits_to_add, 2)
            assert.are.same(augend:find_stateful("273.15", 6), { from = 1, to = 6 })
            assert.are.same(augend.digits_to_add, 2)

            assert.are.same(augend:find_stateful("9.80665", 1), { from = 1, to = 7 })
            assert.are.same(augend.digits_to_add, 0)
            assert.are.same(augend:find_stateful("9.80665", 3), { from = 1, to = 7 })
            assert.are.same(augend.digits_to_add, 5)
            assert.are.same(augend:find_stateful("9.80665", 4), { from = 1, to = 7 })
            assert.are.same(augend.digits_to_add, 5)
            assert.are.same(augend:find_stateful("9.80665", 5), { from = 1, to = 7 })
            assert.are.same(augend.digits_to_add, 5)
            assert.are.same(augend:find_stateful("9.80665", 6), { from = 1, to = 7 })
            assert.are.same(augend.digits_to_add, 5)
        end)

        it("returns nil when no number appears", function()
            assert.are.same(augend:find("", 1), nil)
            assert.are.same(augend:find("foo bar", 1), nil)
        end)
        it("picks up negative number", function()
            assert.are.same(augend:find("-42.195", 1), { from = 1, to = 7 })
            assert.are.same(augend:find("fname-1.3", 1), { from = 6, to = 9 })
        end)
        it("doesn't pick up incomplete decimal fraction", function()
            assert.are.same(augend:find("-42.", 1), nil)
            assert.are.same(augend:find("fname-1.png", 1), nil)
            assert.are.same(augend:find(".1", 1), nil)
        end)
    end)

    describe("add function", function()
        it("can increment integer parts", function()
            augend.digits_to_add = 0
            assert.are.same(augend:add("273.15", 1, 1), { text = "274.15", cursor = 3 })
            assert.are.same(augend:add("273.15", 10, 1), { text = "283.15", cursor = 3 })
            assert.are.same(augend:add("273.15", 10, 4), { text = "283.15", cursor = 3 })
            assert.are.same(augend:add("273.15", 100, 1), { text = "373.15", cursor = 3 })
            assert.are.same(augend:add("273.15", 1000, 1), { text = "1273.15", cursor = 4 })
            assert.are.same(augend:add("273.15", -1, 1), { text = "272.15", cursor = 3 })
            assert.are.same(augend:add("273.15", -10, 1), { text = "263.15", cursor = 3 })
            assert.are.same(augend:add("273.15", -100, 1), { text = "173.15", cursor = 3 })
            assert.are.same(augend:add("273.15", -200, 1), { text = "73.15", cursor = 2 })
            assert.are.same(augend:add("273.15", -270, 1), { text = "3.15", cursor = 1 })
            assert.are.same(augend:add("273.15", -273, 1), { text = "0.15", cursor = 1 })
            assert.are.same(augend:add("273.15", -274, 1), { text = "-0.85", cursor = 2 })
            assert.are.same(augend:add("273.15", -1000, 1), { text = "-726.85", cursor = 4 })
        end)
        it("can increment fragment parts", function()
            augend.digits_to_add = 1
            assert.are.same(augend:add("273.15", 1, 1), { text = "273.25", cursor = 6 })
            assert.are.same(augend:add("273.15", 9, 1), { text = "274.05", cursor = 6 })
            assert.are.same(augend:add("273.15", 10, 1), { text = "274.15", cursor = 6 })
            assert.are.same(augend:add("273.15", 10, 4), { text = "274.15", cursor = 6 })
            assert.are.same(augend:add("273.15", 100, 1), { text = "283.15", cursor = 6 })
            assert.are.same(augend:add("273.15", 1000, 1), { text = "373.15", cursor = 6 })
            assert.are.same(augend:add("273.15", 10000, 1), { text = "1273.15", cursor = 7 })
            assert.are.same(augend:add("273.15", -1, 1), { text = "273.05", cursor = 6 })
            assert.are.same(augend:add("273.15", -2, 1), { text = "272.95", cursor = 6 })
            assert.are.same(augend:add("273.15", -10, 1), { text = "272.15", cursor = 6 })
            assert.are.same(augend:add("273.15", -100, 1), { text = "263.15", cursor = 6 })
            assert.are.same(augend:add("273.15", -1000, 1), { text = "173.15", cursor = 6 })
            assert.are.same(augend:add("273.15", -10000, 1), { text = "-726.85", cursor = 7 })

            augend.digits_to_add = 2
            assert.are.same(augend:add("273.15", 1, 1), { text = "273.16", cursor = 6 })
            assert.are.same(augend:add("273.15", 5, 1), { text = "273.20", cursor = 6 })
            assert.are.same(augend:add("273.15", 10, 1), { text = "273.25", cursor = 6 })
            assert.are.same(augend:add("273.15", 90, 1), { text = "274.05", cursor = 6 })
            assert.are.same(augend:add("273.15", 1000, 1), { text = "283.15", cursor = 6 })

            augend.digits_to_add = 3
            assert.are.same(augend:add("273.15", 1, 1), { text = "273.151", cursor = 7 })
            assert.are.same(augend:add("273.15", 5, 1), { text = "273.155", cursor = 7 })
            assert.are.same(augend:add("273.15", 10, 1), { text = "273.160", cursor = 7 })
        end)
    end)
end)
