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

describe("Test of integer.alias.decimal:", function()
    local augend = integer.alias.decimal

    describe("find function", function()
        it("can find a decimal number", function()
            assert.are.same(augend:find("123", 1), { from = 1, to = 3 })
            assert.are.same(augend:find("123 4567 89", 1), { from = 1, to = 3 })
            assert.are.same(augend:find("123 4567 89", 3), { from = 1, to = 3 })
            assert.are.same(augend:find("123 4567 89", 4), { from = 5, to = 8 })
            assert.are.same(augend:find("123 4567 89", 5), { from = 5, to = 8 })
        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("-123", 1), { from = 2, to = 4 })
            assert.are.same(augend:find("fname-1", 1), { from = 7, to = 7 })
        end)
        it("doesn't pick up hex number", function()
            assert.are.same(augend:find("0xaf", 1), { from = 1, to = 1 })
        end)
    end)

    describe("add function", function()
        it("can increment numbers", function()
            assert.are.same(augend:add("12", 1, 1), { text = "13", cursor = 2 })
            assert.are.same(augend:add("12", 1, 2), { text = "13", cursor = 2 })
            assert.are.same(augend:add("12", 3, 1), { text = "15", cursor = 2 })
            assert.are.same(augend:add("12", 123, 1), { text = "135", cursor = 3 })
            assert.are.same(augend:add("12", -1, 1), { text = "11", cursor = 2 })
            assert.are.same(augend:add("12", -3, 1), { text = "9", cursor = 1 })
            assert.are.same(augend:add("12", -15, 1), { text = "0", cursor = 1 })
        end)
    end)
end)

describe("Test of integer.alias.decimal_int:", function()
    local augend = integer.alias.decimal_int

    describe("find function", function()
        it("can find a decimal number", function()
            assert.are.same(augend:find("123", 1), { from = 1, to = 3 })
            assert.are.same(augend:find("123 4567 89", 1), { from = 1, to = 3 })
            assert.are.same(augend:find("123 4567 89", 3), { from = 1, to = 3 })
            assert.are.same(augend:find("123 4567 89", 4), { from = 5, to = 8 })
            assert.are.same(augend:find("123 4567 89", 5), { from = 5, to = 8 })
        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("-123", 1), { from = 1, to = 4 })
            assert.are.same(augend:find("fname-1", 1), { from = 6, to = 7 })
        end)
    end)

    describe("add function", function()
        it("can increment numbers", function()
            assert.are.same(augend:add("12", 1, 1), { text = "13", cursor = 2 })
            assert.are.same(augend:add("12", 1, 2), { text = "13", cursor = 2 })
            assert.are.same(augend:add("12", 3, 1), { text = "15", cursor = 2 })
            assert.are.same(augend:add("12", 123, 1), { text = "135", cursor = 3 })
            assert.are.same(augend:add("12", -1, 1), { text = "11", cursor = 2 })
            assert.are.same(augend:add("12", -3, 1), { text = "9", cursor = 1 })
            assert.are.same(augend:add("12", -15, 1), { text = "-3", cursor = 2 })
            assert.are.same(augend:add("-3", 1, 1), { text = "-2", cursor = 2 })
            assert.are.same(augend:add("-3", 4, 1), { text = "1", cursor = 1 })
            assert.are.same(augend:add("-3", -24, 1), { text = "-27", cursor = 3 })
        end)
    end)
end)

describe("Test of integer.alias.hex:", function()
    local augend = integer.alias.hex

    describe("find function", function()
        it("can find a hex number", function()
            assert.are.same(augend:find("0x0", 1), { from = 1, to = 3 })
            assert.are.same(augend:find("0xa", 1), { from = 1, to = 3 })
            assert.are.same(augend:find("0x1213", 3), { from = 1, to = 6 })
            assert.are.same(augend:find("0x1a2b", 4), { from = 1, to = 6 })
            assert.are.same(augend:find("0xabcd", 5), { from = 1, to = 6 })
            assert.are.same(augend:find("0xabcdefg", 5), { from = 1, to = 8 })
            assert.are.same(augend:find("0xAB12", 5), { from = 1, to = 6 })
            assert.are.same(augend:find("0xAB12", 5), { from = 1, to = 6 })
        end)
        it("does not detect hex number without `0x`", function()
            assert.are.same(augend:find("0", 1), nil)
            assert.are.same(augend:find("1a1a", 1), nil)
            assert.are.same(augend:find("1A1A", 1), nil)
        end)
        it("does not detect hex number starting with `0X`", function()
            assert.are.same(augend:find("0X1", 1), nil)
        end)
    end)

    describe("add function", function()
        it("can increment numbers", function()
            assert.are.same(augend:add("0x1", 1, 1), { text = "0x2", cursor = 3 })
            assert.are.same(augend:add("0xf", 1, 1), { text = "0x10", cursor = 4 })
            assert.are.same(augend:add("0x12", 8, 1), { text = "0x1a", cursor = 4 })
            assert.are.same(augend:add("0x2020", -1, 1), { text = "0x201f", cursor = 6 })
            assert.are.same(augend:add("0x1F1F", 2, 1), { text = "0x1f21", cursor = 6 })
        end)
    end)
end)

describe([[Test of integer.new {delimiter = ","}:]], function()
    local augend = integer.new { delimiter = "," }

    describe("find function", function()
        it("can find comma-separated integer", function()
            assert.are.same(augend:find("123", 1), { from = 1, to = 3 })
            assert.are.same(augend:find("123,456", 1), { from = 1, to = 7 })
            assert.are.same(augend:find("123,456,789", 1), { from = 1, to = 11 })
            assert.are.same(augend:find("123,456,789", 4), { from = 1, to = 11 })
            assert.are.same(augend:find("123,456,789", 5), { from = 1, to = 11 })
            assert.are.same(augend:find("123,456,789", 7), { from = 1, to = 11 })
        end)
        it("does not consider number of digits", function()
            assert.are.same(augend:find("1,2,3", 1), { from = 1, to = 5 })
            assert.are.same(augend:find("123,4,56", 1), { from = 1, to = 8 })
            assert.are.same(augend:find("123,456,789", 1), { from = 1, to = 11 })
        end)
        it("does not match illegal format", function()
            assert.are.same(augend:find("123, 456", 1), { from = 1, to = 3 })
            assert.are.same(augend:find("123, 456", 4), { from = 6, to = 8 })
            assert.are.same(augend:find("123 ,456", 1), { from = 1, to = 3 })
            assert.are.same(augend:find("foo,1", 1), { from = 5, to = 5 })
        end)
    end)

    describe("add function", function()
        it("can increment numbers", function()
            assert.are.same(augend:add("1,999", 1, 1), { text = "2,000", cursor = 5 })
            assert.are.same(augend:add("9,999,999", 1, 1), { text = "10,000,000", cursor = 10 })
            assert.are.same(augend:add("999,999", 1, 1), { text = "1,000,000", cursor = 9 })
            assert.are.same(augend:add("100,000", -1, 1), { text = "99,999", cursor = 6 })
            assert.are.same(augend:add("1,000", -1, 1), { text = "999", cursor = 3 })
        end)
        it("fixes the place of separators", function()
            assert.are.same(augend:add("19,99", 1, 1), { text = "2,000", cursor = 5 })
            assert.are.same(augend:add("1,0,0,0,0,0", -1, 1), { text = "99,999", cursor = 6 })
        end)
    end)
end)

describe([[Test of integer.new {delimiter = "."}:]], function()
    local augend = integer.new { delimiter = "." }

    describe("find function", function()
        it("can find comma-separated integer", function()
            assert.are.same(augend:find("123", 1), { from = 1, to = 3 })
            assert.are.same(augend:find("123.456", 1), { from = 1, to = 7 })
        end)
        it("does not consider number of digits", function()
            assert.are.same(augend:find("1.2.3", 1), { from = 1, to = 5 })
        end)
        it("does not match illegal format", function()
            assert.are.same(augend:find("123. 456", 1), { from = 1, to = 3 })
            assert.are.same(augend:find("123. 456", 4), { from = 6, to = 8 })
            assert.are.same(augend:find("123 .456", 1), { from = 1, to = 3 })
            assert.are.same(augend:find("foo.1", 1), { from = 5, to = 5 })
        end)
    end)

    describe("add function", function()
        it("can increment numbers", function()
            assert.are.same(augend:add("1.999", 1, 1), { text = "2.000", cursor = 5 })
            assert.are.same(augend:add("9.999.999", 1, 1), { text = "10.000.000", cursor = 10 })
            assert.are.same(augend:add("999.999", 1, 1), { text = "1.000.000", cursor = 9 })
            assert.are.same(augend:add("100.000", -1, 1), { text = "99.999", cursor = 6 })
            assert.are.same(augend:add("1.000", -1, 1), { text = "999", cursor = 3 })
        end)
        it("fixes the place of separators", function()
            assert.are.same(augend:add("19.99", 1, 1), { text = "2.000", cursor = 5 })
            assert.are.same(augend:add("1.0.0.0.0.0", -1, 1), { text = "99.999", cursor = 6 })
        end)
    end)
end)

describe([[Test of integer.new {delimiter = ",", delimiter_digits = 4}:]], function()
    local augend = integer.new { delimiter = ",", delimiter_digits = 4 }

    describe("find function", function()
        it("can find comma-separated integer", function()
            assert.are.same(augend:find("123,456,789", 1), { from = 1, to = 11 })
        end)
    end)

    describe("add function", function()
        it("separates numbers by four digits", function()
            assert.are.same(augend:add("1,999", 1, 1), { text = "2000", cursor = 4 })
            assert.are.same(augend:add("9,999,999", 1, 1), { text = "1000,0000", cursor = 9 })
        end)
    end)
end)
describe([[Test of delimited binary number:]], function()
    local augend = integer.new {
        radix = 2,
        prefix = "0b",
        delimiter = "_",
        delimiter_digits = 4,
    }

    describe("find function", function()
        it("can find comma-separated integer", function()
            assert.are.same(augend:find("0b1010_0101", 1), { from = 1, to = 11 })
        end)
    end)

    describe("add function", function()
        it("separates numbers by four digits", function()
            assert.are.same(augend:add("0b1010_0101", 1, 1), { text = "0b1010_0110", cursor = 11 })
            assert.are.same(augend:add("0b1010_1111", 1, 1), { text = "0b1011_0000", cursor = 11 })
        end)
    end)
end)
