package io.machinecode.then.core;

import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * @author <a href="mailto:brent.n.douglas@gmail.com">Brent Douglas</a>
 * @since 1.0
 */
public class FutureDeferred<T,P> extends DeferredImpl<T,Throwable,P> implements Callable<T>, Runnable {

    protected final Future<? extends T> future;
    protected final long timeout;
    protected final TimeUnit unit;

    public FutureDeferred(final Future<? extends T> future) {
        this.future = future;
        this.timeout = -1;
        this.unit = null;
    }

    public FutureDeferred(final Future<? extends T> future, final long timeout, final TimeUnit unit) {
        this.future = future;
        this.timeout = timeout;
        this.unit = unit;
    }

    @Override
    public void run() {
        final T that;
        try {
            if (this.unit == null) {
                that = future.get();
            } else {
                that = future.get(timeout, unit);
            }
        } catch (final CancellationException e) {
            cancel(true);
            return;
        } catch (final Throwable e) {
            reject(e);
            return;
        }
        resolve(that);
    }

    @Override
    public T call() throws Exception {
        run();
        return unit == null
                ? get()
                : get(timeout, unit);
    }

    public Runnable asRunnable() {
        return this;
    }

    public Callable<T> asCallable() {
        return this;
    }
}

@@ -28,16 +28,58 @@
 .core;%0A%0A
+import io.machinecode.then.api.Deferred;%0A%0A
 import j
@@ -951,57 +951,138 @@
     
-final T that
+getFuture(future, this, timeout, unit)
 ;%0A    
+%7D%0A%0A
     
-try %7B%0A            if (this.
+@Override%0A    public T call() throws Exception %7B%0A        run();%0A        return 
 unit
@@ -1089,19 +1089,16 @@
  == null
-) %7B
 %0A       
@@ -1110,28 +1110,15 @@
     
-that = future.
+? 
 get()
-;
 %0A   
@@ -1130,47 +1130,14 @@
     
-%7D else %7B%0A                that = future.
+    : 
 get(
@@ -1160,193 +1160,311 @@
     
+%7D%0A%0A
     
-    %7D%0A        %7D catch (final CancellationException e) %7B%0A            cancel(true)
+public Runnable asRunnable() %7B%0A        return this;%0A    %7D%0A%0A    public Callable%3CT%3E asCallable() %7B%0A        return this
 ;%0A    
+%7D%0A%0A
     
-    return;%0A        %7D catch (final Throwable e) %7B%0A            reject(e);%0A            return
+public static %3CT,P%3E void getFuture(final Future%3C? extends T%3E future, final Deferred%3CT,Throwable,P%3E def, final long timeout, final TimeUnit unit) %7B%0A        final T that
 ;%0A  
@@ -1469,17 +1469,21 @@
         
-%7D
+try %7B
 %0A       
@@ -1487,80 +1487,29 @@
     
-resolve(that);%0A    %7D%0A%0A    @Override%0A    public T call() throws Exception
+    if (unit == null)
  %7B%0A 
@@ -1511,39 +1511,32 @@
 ) %7B%0A        
-run();%0A
         
 return unit 
@@ -1523,38 +1523,37 @@
         
-return unit == null%0A  
+that = future.get();%0A
         
@@ -1552,33 +1552,32 @@
             
-  ? get()
+%7D else %7B
 %0A           
@@ -1573,34 +1573,46 @@
                 
-: 
+that = future.
 get(timeout, uni
@@ -1623,46 +1623,102 @@
     
-%7D%0A%0A    public Runnable asRunnable() %7B%0A
+        %7D%0A        %7D catch (final CancellationException e) %7B%0A            def.cancel(true);%0A    
     
@@ -1731,79 +1731,130 @@
 turn
- this
 ;%0A    
-%7D%0A%0A
     
-public Callable%3CT%3E asCallable() %7B%0A        return this
+%7D catch (final Throwable e) %7B%0A            def.reject(e);%0A            return;%0A        %7D%0A        def.resolve(that)
 ;%0A  

Add static method to resolve a Deferred from a Future