package fr.umlv.reflect;

import static org.junit.Assert.*;

import java.util.AbstractMap;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.junit.Test;

public class IntrospectorsTest {
  static class A {
    int aValue;

    public A(int aValue) {
      this.aValue = aValue;
    }
    
    public int getAValue() {
      return aValue;
    }
    public void setAValue(int aValue) {
      this.aValue = aValue;
    }
  }
  
  static class B {
    public int getValue() {
      return 777;
    }
    public double notAGet() {
      return 0;
    }
  }
  
  @Test(expected=NullPointerException.class)
  public void testAsMapNull() {
    Introspectors.asMap(null);
  }
  
  @Test
  public void testAsMap() {
    A a = new A(1023);
    Map<String, Object> map = Introspectors.asMap(a);
    assertEquals(1023, map.get("aValue"));
    assertTrue(map.keySet().contains("aValue"));
    assertTrue(map.values().contains(1023));
  }
  
  @Test
  public void testAsMap2() {
    B b = new B();
    Map<String, Object> map = Introspectors.asMap(b);
    assertEquals(777, map.get("value"));
    assertTrue(map.keySet().contains("value"));
    assertTrue(map.values().contains(777));
  }
  
  @Test
  public void testAsMapUnknownGet() {
    A a = new A(45687);
    Map<String, Object> map = Introspectors.asMap(a);
    assertNull(map.get("foo"));
  }
  
  @Test(expected=UnsupportedOperationException.class)
  public void testAsMapPut() {
    A a = new A(-4537);
    Map<String, Object> map = Introspectors.asMap(a);
    map.put("aValue", 12);
  }
  
  @Test(expected=UnsupportedOperationException.class)
  public void testAsMapEntrySet() {
    A a = new A(45);
    Set<Entry<String, Object>> set = Introspectors.asMap(a).entrySet();
    set.iterator().next().setValue("98");
  }
  
  @Test(expected=UnsupportedOperationException.class)
  public void testAsMapEntrySetIterator() {
    A a = new A(445);
    Set<Entry<String, Object>> set = Introspectors.asMap(a).entrySet();
    Iterator<Entry<String, Object>> iterator = set.iterator();
    iterator.next();
    iterator.remove();
  }
  
  @Test
  public void testAsMapAfterCall() {
    A a = new A(879);
    Map<String, Object> map = Introspectors.asMap(a);
    a.setAValue(66);
    assertEquals(66, map.get("aValue"));
  }
  
  @Test
  public void testAsMapValuesAfterCall() {
    A a = new A(745);
    Collection<Object> collection = Introspectors.asMap(a).values();
    a.setAValue(666);
    assertTrue(collection.contains(666));
  }
}
