/*
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.io;

import java.io.Closeable;
import java.io.IOException;
import net.ranides.assira.functional.checked.CheckedConsumer;
import net.ranides.assira.functional.checked.CheckedSupplier;

/**
 * This class represents handle which can be use to retrieve Closeable resource.
 *
 *
 * Handle allows you to postpone creation of resource to the moment of first use.
 *
 * If you close handle, resource will be closed too and become invalid.
 *
 * @param <T> resource
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 */
public interface IOHandle<T> extends Closeable, CheckedSupplier<T, IOException> {

    /**
     * Creates new thread-safe shared resource.
     * Resource is created when you call {@link #get()} first time.
     *
     * It uses "close" operation to release resource.
     * It uses "open" operation to create resource.
     *
     * Resource is created only once, next calls to "get" will return the same instance.
     *
     * @param close close
     * @param open open
     * @param <T> T
     * @return handle
     */
    static <T> IOHandle<T> shared(CheckedConsumer<T,IOException> close, CheckedSupplier<T,IOException> open) {
        return new IOUtils.SharedHandle<>(close, open);
    }

    /**
     * Creates new thread-safe shared resource.
     * Resource is created when you call {@link #get()} first time.
     *
     * If resource if "Closable" it uses "close" operation to release resource.
     * It uses "open" operation to create resource.
     *
     * Resource is created only once, next calls to "get" will return the same instance.
     *
     * @param open open open
     * @param <T> T
     * @return handle
     */
    static <T> IOHandle<T> shared(CheckedSupplier<T,IOException> open) {
        return new IOUtils.SharedHandle<>(open);
    }

    /**
     * Closes handle and created resource
     *
     * @throws IOException on error
     */
    @Override
    void close() throws IOException;

    /**
     * Returns created resource managed by this handle.
     * It creates resource on first call, later calls will create the same instance.
     *
     * Shared handle implements this method to be thread-safe: it synchronizes access to resource.
     *
     * @return resource
     * @throws IOException on error
     */
    @Override
    T get() throws IOException;

    /**
     * Returns true if handle contains already created resource.
     *
     * @return boolean
     */
    boolean opened();
    
    
}
