'use strict'

const assert = require('assert')
const I = require('../lib')
const _ = require('lodash')

describe('operations on arrays', function () {
  const numbers = [1, 4, 9]

  it('maps an array of numbers to an array of square roots', function () {
    const roots = I.map(Math.sqrt, numbers)
    assert.deepEqual(roots, [1, 2, 3])
  })

  it('accepts a Map object instead of a function', function () {
    const sqrt = new Map([
      [1, 1],
      [4, 2],
      [9, 3]
    ])

    const roots = I.map(sqrt, numbers)
    assert.deepEqual(roots, [1, 2, 3])
  })

  it('is curried', function () {
    const roots = I.map(Math.sqrt)(numbers)
    assert.deepEqual(roots, [1, 2, 3])
  })
})

describe('operations on Maps', function () {
  it('maps entries of a Map to another Map', function () {
    const map = new Map([['one', 1], ['two', 2], ['three', 3]])
    const inverted = I.map((pair) => [pair[1], pair[0]], map)
    assert(_.isEqual(inverted, new Map([[1, 'one'], [2, 'two'], [3, 'three']])))
  })
})

describe('operations on Objects', function () {
  it('maps properties of an Object to another Object', function () {
    const object = {one: 1, two: 2, three: 3}
    const inverted = I.map((property) => [property[1], property[0]], object)
    assert(_.isEqual(inverted, {1: 'one', 2: 'two', 3: 'three'}))
  })
})

describe('operations on iterables', function () {
  it('maps an array of numbers to an array of square roots', function () {
    const numbers = function * () {
      yield 1
      yield 4
      yield 9
    }

    const roots = I.map(Math.sqrt, numbers())
    assert.deepEqual(I.to(Array, roots), [1, 2, 3])
  })
})

it('operations on asyncIterables', function () {
  const numbers = I.to('AsyncIterable', [1, 4, 9])

  return I.to(Array, I.map(Math.sqrt, numbers)).then((roots) => {
    assert.deepEqual(roots, [1, 2, 3])
  })
})
