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

import java.io.Serializable;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import net.ranides.assira.functional.CoFunction;
import net.ranides.assira.functional.ProjectionFunction;
import net.ranides.assira.generic.CompareUtils;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class TWrapper<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    private final T value;

    public TWrapper(T value) {
        this.value = value;
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(this.value);
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof TWrapper)) {
            return false;
        }
        final TWrapper other = (TWrapper) obj;
        return CompareUtils.equals(this.value, other.value);
    }

    public static <T> Function<TWrapper<T>, T> unwrap() {
        return (Function<TWrapper<T>, T> & Serializable) w -> (w == null) ? null : w.value;
    }

    public static <T> CoFunction<TWrapper<T>, T> wrap() {
        return (CoFunction<TWrapper<T>, T> & Serializable) t -> (t == null) ? null : new TWrapper<>(t);
    }

    public static <T> ProjectionFunction<TWrapper<T>, T> projection() {
        return ProjectionFunction.produce(unwrap(), wrap());
    }

    public static <K,V> Map<K,TWrapper<V>> into(Map<K,TWrapper<V>> target, TMap.TItems<K, V> items) {
        for(TMap.TItem<K,V> item : items) {
            target.put(item.key(), new TWrapper<>(item.value()));
        }
        return target;
    }
    
    public static <V> Set<TWrapper<V>> into(Set<TWrapper<V>> target, TCollection.TItems<V> items) {
        for(TCollection.TItem<V> item : items) {
            target.add(new TWrapper<>(item.value()));
        }
        return target;
    }

}