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

import java.util.AbstractSet;
import java.util.Comparator;
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.collection.lookups.AVLTreeLookup;
import net.ranides.assira.generic.CompareUtils;
import net.ranides.assira.test.TMap;
import org.junit.Test;

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

        public ATMap(Comparator<TPoint> cmp) {
            data = new TreeMap<>(cmp);
        }

        @Override
        public Integer put(TPoint key, Integer value) {
            return data.put(key, value);
        }

        @Override
        public Integer remove(Object key) {
            if(!(key instanceof TPoint)) {
                return null;
            }
            return data.remove(key);
        }

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

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

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

        @Override
        public Integer get(Object key) {
            return data.get(key);
        }

        @Override
        public Set<Entry<TPoint, Integer>> entrySet() {
            return new AbstractSet<Entry<TPoint, Integer>>() {

                @Override
                public Iterator<Entry<TPoint, Integer>> iterator() {
                    return IteratorUtils.map(data.entrySet().iterator(), entry -> new BasicEntry<>(entry.getKey(), entry.getValue()));
                }

                @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();
        }

    }
    
}
