package app.issue.commons.java;

import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.google.common.base.Function;

import java.util.ArrayList;
import java.util.List;

import timber.log.Timber;

import static com.google.common.base.Optional.fromNullable;

@SuppressWarnings("Guava")
public interface SafeIteration<ELEMENT, PROCESS_RESULT> {

    PROCESS_RESULT process(ELEMENT e) throws Exception;

    @NonNull
    default List<PROCESS_RESULT> iterate(Iterable<ELEMENT> elements) {
        List<PROCESS_RESULT> result = new ArrayList<>();
        for (ELEMENT element : fromNullable(elements).or(new ArrayList<>())) {
            PROCESS_RESULT eResult = null;
            try {
                eResult = process(element);
            } catch (Exception exception) {
                Timber.e(exception);
            }
            if (eResult != null) {
                result.add(eResult);
            }
        }
        Timber.d("elements=%s result=%s", elements, result);
        return result;
    }

    @Nullable
    default PROCESS_RESULT once(ELEMENT element) {
        try {
            return process(element);
        } catch (Exception e) {
            Timber.e(e);
        }
        return null;
    }

    static <E, R> List<R> iterate(Iterable<E> elements, Function<E, R> function) {
        SafeIteration<E, R> safeIteration = function::apply;
        return safeIteration.iterate(elements);
    }

    static <E, R> R once(E e, Function<E, R> function) {
        SafeIteration<E, R> safeIteration = function::apply;
        return safeIteration.once(e);
    }
}
