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

import java.util.AbstractSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import net.ranides.assira.collection.iterators.IteratorUtils;
import net.ranides.assira.collection.mockup.TMaps;
import net.ranides.assira.collection.mockup.TPoint;
import net.ranides.assira.ContractTesters;
import net.ranides.assira.generic.CompareUtils;
import net.ranides.assira.generic.ValueUtils;
import org.junit.Test;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class LookupTest {
    
    @Test
    public void testSuite() {
        ContractTesters.runner()
            .param("map!", TMaps.MAP_PI)
            .function(new int[0], array -> TMaps.MAP_PI.list(array).into(new ATLookup()))
			.run();
    }
    
    private static class ATLookup extends ALookup<TPoint> {
        
        private final Map<TPoint, Integer> data = new TreeMap<>(TMaps.MAP_PI.comparator());

        @Override
        public int put(TPoint key, int value) {
            return ValueUtils.or(data.put(key, value), defaultReturnValue());
        }

        @Override
        public int removeInt(Object key) {
            if(!containsKey(key)) {
                return defaultReturnValue();
            }
            return data.remove(key);
        }

        @Override
        public void clear() {
            data.clear();
        }

        
        @Override
        public boolean containsValue(int v) {
            return data.containsValue(v);
        }

        @Override
        public boolean containsKey(Object key) {
            if(!(key instanceof TPoint)) {
                return false;
            }
            return data.containsKey(key);
        }

        @Override
        public int getInt(Object key) {
            return ValueUtils.or(data.get(key), defaultReturnValue());
        }

        @Override
        public Set<LookupEntry<TPoint>> fastEntrySet() {
            return new AbstractSet<LookupEntry<TPoint>>() {

                @Override
                public Iterator<LookupEntry<TPoint>> iterator() {
                    return IteratorUtils.map(data.entrySet().iterator(), entry -> new EntryWrapper<>(entry));
                }

                @Override
                public int size() {
                    return data.size();
                }
                
                @SuppressWarnings("unchecked")
                @Override
                public boolean remove(Object object) {
                    if(object instanceof Entry) {
                        Entry<TPoint, Integer> entry = (Entry<TPoint, Integer>)object;
                        return data.remove(entry.getKey(), entry.getValue());
                    }
                    return false;
                }

                @SuppressWarnings("unchecked")
                @Override
                public boolean contains(Object object) {
                    if(!(object instanceof Entry)) {
                        return false;
                    }
                    Entry<TPoint, Integer> entry = (Entry<TPoint, Integer>)object;
                    if(!data.containsKey(entry.getKey())) {
                        return false;
                    }
                    return CompareUtils.equals(data.get(entry.getKey()), entry.getValue());
                }
                
            };
        }

        @Override
        public int size() {
            return data.size();
        }

    }
    
}
