local _ = require('lodash')
describe('Array module', function()
    it('should support chunk', function() 
        local expected = '{{"x", "y", "z", 1}, {2, 3, 4, true}, {false}}' 
        local actual = _.str(_.chunk({'x', 'y', 'z', 1, 2, 3, 4, true , false}, 4))
        assert.is.equal(expected, actual)

        expected = '{{"x", "y", "z"}, {1, 2, 3}, {4, true, false}}'
        actual = _.str(_.chunk({'x', 'y', 'z', 1, 2, 3, 4, true , false}, 3)) 
        assert.is.equal(expected, actual)
    end)
    it('should support join', function() 
        local expected = 'x,y,z' 
        -- local actual = _.join({'x', 'y', 'z', 1, 2, 3, 4, true , false})
        local actual = _.join({'x', 'y', 'z'})
        assert.is.equal(expected, actual)

        assert.is.equal('x y z', _.join({'x', 'y', 'z'}, ' '))
    end)
    it('should support compact', function()
        assert.is.equal('{"x", "y", 1, 2, 3, true}', _.str(_.compact({'x', 'y', nil, 1, 2, 3, false, true , false})))
    end)
    it('should support difference', function()
        assert.is.equal('{3, 2}', _.str(_.difference({3, 1, 2, 9, 5, 9}, {4, 5}, {9, 1})) )
        assert.is.equal('{"q", 3, false, false}', _.str(_.difference({'x', 'q', '2', 3, false, true, false}, {true}, {'2', 'x'})))
    end)
    it('should support drop', function()
        assert.is.equal('{3, 4, 5, 6}', _.str(_.drop({1, 2, 3, 4, 5, 6}, 2)))
    end)
    it('should support dropRight', function()
        assert.is.equal('{1, 2, 3, 4}', _.str(_.dropRight({1, 2, 3, 4, 5, 6}, 2)))
    end)
    it('should support dropRightWhile', function()
        assert.is.equal('{1, 5, 2, 3}', _.str(_.dropRightWhile({1, 5, 2, 3, 4, 5, 4, 4}, function(n)
            return n > 3
        end)))
    end)
    it('should support dropWhile', function()
        assert.is.equal('{3, 4, 5, 4, 4, 2}', _.str(_.dropWhile({1, 2, 2, 3, 4, 5, 4, 4, 2}, function(n)
        return n < 3
        end)))
    end)
    it('should support fill', function()
        local array = {1, 2, 3, 4, 5}; 
        _.fill(array, 'x', 2, #array - 1)
        assert.is.equal('{1, "x", "x", "x", 5}', _.str(array))

        local array = {1, 2, 3, 4, 5}; 
        _.fill(array, 'x', 5, 4)
        assert.is.equal('{1, 2, 3, "x", "x"}', _.str(array))

        local array = {1, 2, 3, 4, 5}; 
        _.fill(array, 'x')
        assert.is.equal('{"x", "x", "x", "x", "x"}', _.str(array))
    end)
    it('should support findIndex', function()
        assert.is.equal(3, _.findIndex({{a = 1}, {a = 2}, {a = 3}, {a = 2}, {a = 3}}, function(v)
            return v.a == 3
        end))
    end)
    it('should support findLastIndex', function()
        assert.is.equal(5, _.findLastIndex({{a = 1}, {a = 2}, {a = 3}, {a = 2}, {a = 3}}, function(v)
            return v.a == 3
        end))
    end)
    it('should support first', function()
        assert.is.equal('w', _.first({'w', 'x', 'y', 'z'}))
    end)
    it('should support flatten', function()
        assert.is.equal('{1, 2, 3, 4, {5, 6}}', _.str(_.flatten({1, 2, {3, 4, {5, 6}}})))
        assert.is.equal('{1, 2, 3, 4, 5, 6}', _.str(_.flatten({1, 2, {3, 4, {5, 6}}}, true)))
    end)
    it('should support flattenDeep', function()
        assert.is.equal('{1, 2, 3, 4, 5, 6}', _.str(_.flattenDeep({1, 2, {3, 4, {5, 6}}})))
    end)
    it('should support indexOf', function()
        assert(3, _.indexOf({2, 3, 'x', 4, 'x'}, 'x'))
    end)
    it('should support initial', function()
        assert.is.equal('{1, 2, 3}', _.str(_.initial({1, 2, 3, 'a'})))
    end)
    it('should support intersection', function()
        assert.is.equal('{2}', _.str(_.intersection({1, 2}, {4, 2}, {2, 1})))
        assert.is.equal('{}', _.str(_.intersection({1, 2, 3}, {4, 2}, {1, 3})))
    end)
    it('should support last', function()
        assert.is.equal('z', _.last({'w', 'x', 'y', 'z'}))
    end)
    it('should support lastIndexOf', function()
        assert.is.equal(5, _.lastIndexOf({2, 3, 'x', 4, 'x'}, 'x'))
    end)
    it('should support pull', function()
        assert.is.equal('{1, 4, 5, 4, 1}', _.str(_.pull({1, 2, 3, 4, 5, 4, 1, 2, 3}, 2, 3)))
    end)
    it('should support pullAt', function()
        local array = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
        local t = _.pullAt(array, 4, 9, 8)
        assert.is.equal('{"a", "b", "c", "e", "f", "g", "j"}', _.str(array))
        assert.is.equal('{"d", "h", "i"}', _.str(t))
    end)
    it('should support remove', function()
        local array = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 2, 3, 4}
        local t = _.remove(array, function(value)
            return value > 4
        end)
        assert.is.equal('{1, 2, 3, 4, 1, 2, 3, 4, 2, 3, 4}', _.str(array))
        assert.is.equal('{5, 6, 7, 5, 6}', _.str(t))
    end)
    it('should support tail (temporarily named rest)', function()
        assert.is.equal('{2, 3, "a"}', _.str(_.rest({1, 2, 3, 'a'})))
        assert.are.same({}, _.tail({2}))
    end)
    it('should support reverse', function()
        assert.is.equal('{"a", 3, 2, 1}', _.str(_.reverse({1, 2, 3, 'a'})))
    end)
    it('should support slice', function()
        assert.is.equal('{2, 3, 4}', _.str(_.slice({1, 2, 3, 4, 5, 6}, 2, 4)))
        assert.is.equal('{3, 4, 5, 6}', _.str(_.slice({1, 2, 3, 4, 5, 6}, 3)))
    end)
    it('should support take', function()
        assert.is.equal('{1, 2, 3}', _.str(_.take({1, 2, 3, 4, 5}, 3)))
    end)
    it('should support takeRight', function()
        assert.is.equal('{3, 4, 5}', _.str(_.takeRight({1, 2, 3, 4, 5}, 3)))
    end)
    it('should support takeRightWhile', function()
        assert.is.equal('{5, 6, 7, 8}', _.str(_.takeRightWhile({9, 1, 2, 3, 4, 5, 6, 7, 8}, function(n)
            return n > 4
        end)))
    end)
    it('should support takeWhile', function()
        assert.is.equal('{1, 2, 3, 4}', _.str(_.takeWhile({1, 2, 3, 4, 5, 6, 7, 8, 0}, function(n)
            return n < 5
        end)))
    end)
    it('should support union', function()
        assert.is.equal('{1, 2, 4}', _.str(_.union({1, 2}, {4, 2}, {2, 1})))
    end)
    it('should support uniq', function()
        assert.is.equal('{1, 3, 2, 4, 5}', _.str(_.uniq({1, 3, 2, 3, 4, 2, 5})))
        assert.is.equal('{{["x"]=1}, {["x"]=2}, {["x"]=3}}', _.str(_.uniq({{x=1}, {x=2}, {x=2}, {x=3}, {x=1}}, function(n)
            return n.x
        end)))
    end)
    it('should support without', function()
        assert.is.equal('{2, 3, 2, 3, 2}', _.str(_.without({1, 1, 2, 3, 2, 3, 5, 5, 1, 2},  5, 1)))
    end)
    it('should support zip and unzip', function()
        local t = _.zip({'a', 'b', 'c'}, {1, 2, 3}, {10, 20, 30})
        assert.is.equal('{{"a", 1, 10}, {"b", 2, 20}, {"c", 3, 30}}', _.str(t) )
        assert.is.equal('{{"a", "b", "c"}, {1, 2, 3}, {10, 20, 30}}', _.str(_.unzip(t)))
    end)
    it('should support zipObject', function()
        local s = _.zipObject({{'fred', 30}, {'alex', 20}})
        assert.are.same({["fred"]=30, ["alex"]=20}, s)
        local s =  _.zipObject({'fred', 'alex'}, {30, 20})
        assert.are.same({["fred"]=30, ["alex"]=20}, s)
    end)
end)