// Copyright (c) 2014 Quildreen Motta <quildreen@gmail.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/**
 * Converts functions written for continuation-passing style to fuctions that
 * work on Futures.
 *
 * @module async/lift
 */

// -- Dependencies -----------------------------------------------------
var Future = require('data.future')


// -- Aliases ----------------------------------------------------------
var toArray = Function.call.bind([].slice)


// -- Implementation ---------------------------------------------------

/**
 * Converts a function that takes a simple continuation.
 *
 * @method
 * @summary (α₁, α₂, ..., αₙ, (β → Void)) → (α₁, α₂, ..., αₙ → Future[Void, β])
 */
exports.lift = lift
function lift(f) {
  return function _lift() {
    var args  = toArray(arguments)
    var _this = this
    return new Future(function _lift$Future(_, resolve) {
                        f.apply(null, args.concat([resolve])) })}
}

/**
 * Converts a function that takes a node-style continuation.
 *
 * @method
 * @summary (α₁, α₂, ..., αₙ, (β, γ → Void)) → (α₁, α₂, ..., αₙ → Future[β, γ])
 */
exports.liftNode = liftNode
function liftNode(f) {
  return function _liftNode() {
    var args  = toArray(arguments)
    var _this = this
    return new Future(function _liftNode$Future(_, resolve) {
                        f.apply(null, args.concat([resolve])) })}
}

@@ -1196,16 +1196,71 @@
 ng style
+, and similar%0A * control structures (e.g.: Promises/A+)
  to fuct
@@ -1268,19 +1268,16 @@
 ons that
-%0A *
  work on
@@ -1935,21 +1935,8 @@
 tion
- _lift$Future
 (_, 
@@ -2351,104 +2351,1394 @@
 tion
- _liftNode$Future(_, resolve) %7B%0A                        f.apply(null, args.concat(%5Bresolve%5D)) %7D)%7D%0A
+(reject, resolve) %7B%0A                        f.apply(null, args.concat(%5Bhandle%5D))%0A%0A                        function handle(err, data) %7B%0A                          if (err)  reject(err)%0A                          else      resolve(data) %7D%7D)%7D%0A%7D%0A%0A/**%0A * Converts a Future to a node-style function.%0A *%0A * @method%0A * @summary Future%5B%CE%B1, %CE%B2%5D %E2%86%92 (%CE%B1%7Cnull, %CE%B2%7Cnull %E2%86%92 Void)%0A */%0Aexports.toNode = toNode%0Afunction toNode(a) %7B%0A  return function(f) %7B%0A    a.fork( function(e)%7B f(e, null) %7D%0A          , function(v)%7B f(null, v) %7D)%0A  %7D%0A%7D%0A%0A/**%0A * Converts a Promise/A+ to a Future.%0A *%0A * (Do note that it's impossible to give sensible types to Promises/A+, since%0A * it badly breaks parametricity).%0A *%0A * @method%0A * @summary Promise%5BMaybePromise%5B%CE%B1%5D, MaybePromise%5B%CE%B2%5D%5D %E2%86%92 Future%5B%CE%B1, %CE%B2%5D%0A */%0Aexports.fromPromise = fromPromise%0Afunction fromPromise(p) %7B return new Future(function(reject, resolve) %7B%0A  p.then(reject, resolve)%0A%7D)%7D%0A%0A/**%0A * Converts from Future to Promise/A+.%0A *%0A * (Do note that nested futures are *NOT* flattened, just %60join%60 it 'till you%0A * get to the value itself, if you care about passing just the value)%0A *%0A * @method%0A * @summary%0A *   PromiseConstrutor %E2%86%92 Future%5B%CE%B1, %CE%B2%5D %E2%86%92 Promise%5B%CE%B1, %CE%B2%5D%0A *   new PromiseConstructor(((%CE%B1 %E2%86%92 Void), (%CE%B2 %E2%86%92 Void) %E2%86%92 Void)) %E2%86%92 Promise%5B%CE%B1, %CE%B2%5D%0A */%0Aexports.toPromise = toPromise%0Afunction toPromise(Promise, a) %7B return new Promise(function(reject, resolve) %7B%0A  a.fork(reject, resolve)%0A%7D)
 %7D%0A

Support Promises/A+ conversions.