// Path: src/main/java/io/advantageous/reakt/exception/RejectedPromiseException.java
// public class RejectedPromiseException extends RuntimeException {
// 
//     public RejectedPromiseException(String s) {
//         super(s);
//     }
// 
//     public RejectedPromiseException(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public RejectedPromiseException(Throwable cause) {
//         super(cause);
//     }
// }
// 
// Path: src/main/java/io/advantageous/reakt/impl/ResultImpl.java
// public class ResultImpl<T> implements Result<T> {
// 
//     private final Object object;
// 
//     public ResultImpl(final Object object) {
//         this.object = object;
//     }
// 
//     @Override
//     public Result<T> thenExpect(final Consumer<Expected<T>> consumer) {
//         if (success()) consumer.accept(expect());
//         return this;
//     }
// 
//     @Override
//     public Result<T> then(final Consumer<T> consumer) {
//         if (success()) consumer.accept(get());
//         return this;
//     }
// 
//     @Override
//     public Result<T> catchError(final Consumer<Throwable> handler) {
//         if (failure()) handler.accept(cause());
//         return this;
//     }
// 
//     public boolean success() {
//         return !(this.object instanceof Throwable);
//     }
// 
//     @Override
//     public boolean complete() {
//         return true;
//     }
// 
//     public boolean failure() {
//         return this.object instanceof Throwable;
//     }
// 
//     @Override
//     public Throwable cause() {
//         return this.object instanceof Throwable ? (Throwable) this.object : null;
//     }
// 
//     @SuppressWarnings("unchecked")
//     public Expected<T> expect() {
//         if (failure()) throw new IllegalStateException(cause());
//         return Expected.ofNullable((T) this.object);
//     }
// 
//     @SuppressWarnings("unchecked")
//     public T get() {
//         if (failure()) {
//             if (cause() instanceof RuntimeException) {
//                 throw (RuntimeException) cause();
//             } else {
//                 throw new ResultFailedException(cause());
//             }
//         }
//         return (T) this.object;
//     }
// 
//     @Override
//     @SuppressWarnings("unchecked")
//     public T orElse(final T other) {
//         return success() ? (T) this.object : other;
//     }
// 
// }
// 
// Path: src/main/java/io/advantageous/reakt/Result.java
// static Result<Void> doneResult() {
//     return DONE;
// }


import static io.advantageous.reakt.Result.doneResult;
import io.advantageous.reakt.exception.RejectedPromiseException;
import io.advantageous.reakt.impl.ResultImpl;
import java.util.function.Consumer;
/*
 *
 *  Copyright (c) 2016. Rick Hightower, Geoff Chandler
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *    		http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package io.advantageous.reakt;




/**
 * A generic event handler which can be thought of as a callback handler.
 * <p>
 * This is like an async future or promise.
 * <p>
 * This was modeled after QBit's callback, and JavaScripts callbacks.
 * The {@link Result} result represents the result or error from an async operation.
 * <p>
 * A {@code CallbackHandler} is a {@code Consumer} and can be used anywhere a consumer is used.
 * This is for easy integration with non-Reakt libs and code bases.
 * <p>
 *
 * @param <T> type of result returned from callback
 * @author Rick Hightower
 * @author Geoff Chandler
 */
public interface CallbackHandler<T> extends Consumer<T>, Callback<T> {

    /**
     * (Client view)
     * A result was returned so handle it.
     * <p>
     * This is registered from the callers (or event receivers perspective).
     * A client of a service would override {@code onResult}.
     *
     * @param result to handle
     */
    void onResult(Result<T> result);


    /**
     * (Service view)
     * This allows services to send back a failed result easily to the client/handler.
     * <p>
     * This is a helper methods for producers (services that produce results) to send a failed result.
     *
     * @param error error
     */
    default void reject(final Throwable error) {
        onResult(new ResultImpl<>(error));
    }


    /**
     * (Service view)
     * This allows services to send back a failed result easily to the client/handler.
     * <p>
     * This is a helper methods for producers (services that produce results) to send a failed result.
     *
     * @param errorMessage error message
     */
    default void reject(final String errorMessage) {
        reject(new RejectedPromiseException(errorMessage));
    }


    /**
     * (Service view)
     * This allows services to send back a failed result easily to the client/handler.
     * <p>
     * This is a helper methods for producers (services that produce results) to send a failed result.
     *
     * @param errorMessage error message
     * @param error        exception
     */
    default void reject(final String errorMessage, final Throwable error) {
        reject(new RejectedPromiseException(errorMessage, error));
    }

    /**
     * Calls replayDone, for VOID callback only. ES6 promise style.
     */
    @SuppressWarnings("unused")
    default void resolve() {
        onResult((Result<T>) doneResult());
    }

    /**
     * Resolve resolves a promise.
     *
     * @param result makes it more compatible with ES6 style promises
     */
    @SuppressWarnings("unused")
    default void resolve(final T result) {
// Path: src/main/java/io/advantageous/reakt/exception/RejectedPromiseException.java
// public class RejectedPromiseException extends RuntimeException {
// 
//     public RejectedPromiseException(String s) {
//         super(s);
//     }
// 
//     public RejectedPromiseException(String message, Throwable cause) {
//         super(message, cause);
//     }
// 
//     public RejectedPromiseException(Throwable cause) {
//         super(cause);
//     }
// }
// 
// Path: src/main/java/io/advantageous/reakt/impl/ResultImpl.java
// public class ResultImpl<T> implements Result<T> {
// 
//     private final Object object;
// 
//     public ResultImpl(final Object object) {
//         this.object = object;
//     }
// 
//     @Override
//     public Result<T> thenExpect(final Consumer<Expected<T>> consumer) {
//         if (success()) consumer.accept(expect());
//         return this;
//     }
// 
//     @Override
//     public Result<T> then(final Consumer<T> consumer) {
//         if (success()) consumer.accept(get());
//         return this;
//     }
// 
//     @Override
//     public Result<T> catchError(final Consumer<Throwable> handler) {
//         if (failure()) handler.accept(cause());
//         return this;
//     }
// 
//     public boolean success() {
//         return !(this.object instanceof Throwable);
//     }
// 
//     @Override
//     public boolean complete() {
//         return true;
//     }
// 
//     public boolean failure() {
//         return this.object instanceof Throwable;
//     }
// 
//     @Override
//     public Throwable cause() {
//         return this.object instanceof Throwable ? (Throwable) this.object : null;
//     }
// 
//     @SuppressWarnings("unchecked")
//     public Expected<T> expect() {
//         if (failure()) throw new IllegalStateException(cause());
//         return Expected.ofNullable((T) this.object);
//     }
// 
//     @SuppressWarnings("unchecked")
//     public T get() {
//         if (failure()) {
//             if (cause() instanceof RuntimeException) {
//                 throw (RuntimeException) cause();
//             } else {
//                 throw new ResultFailedException(cause());
//             }
//         }
//         return (T) this.object;
//     }
// 
//     @Override
//     @SuppressWarnings("unchecked")
//     public T orElse(final T other) {
//         return success() ? (T) this.object : other;
//     }
// 
// }
// 
// Path: src/main/java/io/advantageous/reakt/Result.java
// static Result<Void> doneResult() {
//     return DONE;
// }


// Path: src/main/java/io/advantageous/reakt/CallbackHandler.java
import static io.advantageous.reakt.Result.doneResult;
import io.advantageous.reakt.exception.RejectedPromiseException;
import io.advantageous.reakt.impl.ResultImpl;
import java.util.function.Consumer;

/*
 *
 *  Copyright (c) 2016. Rick Hightower, Geoff Chandler
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *    		http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package io.advantageous.reakt;




/**
 * A generic event handler which can be thought of as a callback handler.
 * <p>
 * This is like an async future or promise.
 * <p>
 * This was modeled after QBit's callback, and JavaScripts callbacks.
 * The {@link Result} result represents the result or error from an async operation.
 * <p>
 * A {@code CallbackHandler} is a {@code Consumer} and can be used anywhere a consumer is used.
 * This is for easy integration with non-Reakt libs and code bases.
 * <p>
 *
 * @param <T> type of result returned from callback
 * @author Rick Hightower
 * @author Geoff Chandler
 */
public interface CallbackHandler<T> extends Consumer<T>, Callback<T> {

    /**
     * (Client view)
     * A result was returned so handle it.
     * <p>
     * This is registered from the callers (or event receivers perspective).
     * A client of a service would override {@code onResult}.
     *
     * @param result to handle
     */
    void onResult(Result<T> result);


    /**
     * (Service view)
     * This allows services to send back a failed result easily to the client/handler.
     * <p>
     * This is a helper methods for producers (services that produce results) to send a failed result.
     *
     * @param error error
     */
    default void reject(final Throwable error) {
        onResult(new ResultImpl<>(error));
    }


    /**
     * (Service view)
     * This allows services to send back a failed result easily to the client/handler.
     * <p>
     * This is a helper methods for producers (services that produce results) to send a failed result.
     *
     * @param errorMessage error message
     */
    default void reject(final String errorMessage) {
        reject(new RejectedPromiseException(errorMessage));
    }


    /**
     * (Service view)
     * This allows services to send back a failed result easily to the client/handler.
     * <p>
     * This is a helper methods for producers (services that produce results) to send a failed result.
     *
     * @param errorMessage error message
     * @param error        exception
     */
    default void reject(final String errorMessage, final Throwable error) {
        reject(new RejectedPromiseException(errorMessage, error));
    }

    /**
     * Calls replayDone, for VOID callback only. ES6 promise style.
     */
    @SuppressWarnings("unused")
    default void resolve() {
        onResult((Result<T>) doneResult());
    }

    /**
     * Resolve resolves a promise.
     *
     * @param result makes it more compatible with ES6 style promises
     */
    @SuppressWarnings("unused")
    default void resolve(final T result) {
        onResult(new ResultImpl<>(result));