// Test pronto functions
// Tests for fallback, parallel, race, sequence, time_limit, requestorize, objectify

var test_count = 0

function make_requestor(name, delay_seconds, should_succeed) {
  return function(callback, value) {
    log.console(`Starting ${name} with value: ${value}`)
    if (delay_seconds > 0) {
      $delay(function() {
        if (should_succeed) {
          log.console(`${name} succeeded with: ${value + 1}`)
          callback(value + 1)
        } else {
          log.console(`${name} failed`)
          callback(null, `${name} error`)
        }
      }, delay_seconds)
    } else {
      if (should_succeed) {
        log.console(`${name} succeeded immediately with: ${value + 1}`)
        callback(value + 1)
      } else {
        log.console(`${name} failed immediately`)
        callback(null, `${name} error`)
      }
    }
  }
}

return {
  test_fallback: function() {
    log.console("Testing fallback...")
    var req1 = make_requestor("fallback_req1", 0.1, false)  // fails
    var req2 = make_requestor("fallback_req2", 0.1, true)   // succeeds
    var req3 = make_requestor("fallback_req3", 0.1, true)   // should not run

    fallback([req1, req2, req3])(function(result, reason) {
      if (result != null) {
        log.console(`Fallback succeeded: ${result}`)
      } else {
        log.console(`Fallback failed: ${reason}`)
      }
    }, 10)
  },

  test_parallel: function() {
    log.console("Testing parallel...")
    var req1 = make_requestor("parallel_req1", 0.2, true)
    var req2 = make_requestor("parallel_req2", 0.1, true)
    var req3 = make_requestor("parallel_req3", 0.3, true)

    parallel([req1, req2, req3])(function(results, reason) {
      if (results != null) {
        log.console(`Parallel results: ${results}`)
      } else {
        log.console(`Parallel failed: ${reason}`)
      }
    }, 100)
  },

  test_race: function() {
    log.console("Testing race...")
    var req1 = make_requestor("race_req1", 0.3, true)  // slow
    var req2 = make_requestor("race_req2", 0.1, true)  // fast winner
    var req3 = make_requestor("race_req3", 0.2, true)  // medium

    race([req1, req2, req3])(function(result, reason) {
      if (result != null) {
        log.console(`Race winner: ${result}`)
      } else {
        log.console(`Race failed: ${reason}`)
      }
    }, 200)
  },

  test_sequence: function() {
    log.console("Testing sequence...")
    var req1 = make_requestor("seq_req1", 0.1, true)
    var req2 = make_requestor("seq_req2", 0.1, true)
    var req3 = make_requestor("seq_req3", 0.1, true)

    sequence([req1, req2, req3])(function(result, reason) {
      if (result != null) {
        log.console(`Sequence result: ${result}`)
      } else {
        log.console(`Sequence failed: ${reason}`)
      }
    }, 1000)
  },

  test_time_limit: function() {
    log.console("Testing time_limit...")
    var slow_req = make_requestor("slow_req", 0.5, true)  // takes 0.5s
    var timed_req = time_limit(slow_req, 0.2)  // 0.2s limit

    timed_req(function(result, reason) {
      if (result != null) {
        log.console(`Time limit succeeded: ${result}`)
      } else {
        log.console(`Time limit failed: ${reason}`)
      }
    }, 100)
  },

  test_requestorize: function() {
    log.console("Testing requestorize...")
    var add_one = function(x) { return x + 1 }
    var req = requestorize(add_one)

    req(function(result, reason) {
      if (result != null) {
        log.console(`Requestorize result: ${result}`)
      } else {
        log.console(`Requestorize failed: ${reason}`)
      }
    }, 42)
  },

  test_objectify: function() {
    log.console("Testing objectify...")
    var req_a = make_requestor("obj_req_a", 0.1, true)
    var req_b = make_requestor("obj_req_b", 0.1, true)
    var req_c = make_requestor("obj_req_c", 0.1, true)

    var parallel_obj = objectify(parallel)
    var req = parallel_obj({a: req_a, b: req_b, c: req_c})

    req(function(result, reason) {
      if (result != null) {
        log.console(`Objectify result: ${result}`)
      } else {
        log.console(`Objectify failed: ${reason}`)
      }
    }, 1000)
  }
}