package org.bridj;

import java.io.FileNotFoundException;

import java.util.Collection;

import org.junit.Test;
import static org.junit.Assert.*;

import org.bridj.ann.*;
import org.bridj.*;

///http://www.codesourcery.com/public/cxx-abi/cxx-vtable-ex.html
public class TypedPointersTest {
	
	public static class MyPtr extends TypedPointer {
		public MyPtr(long peer) {
			super(peer);
		}
		public MyPtr(Pointer peer) {
			super(peer);
		}
	}
	
	@Library("test")
	public static class MyStruct extends StructObject {
		@Field(0)
		//public native Pointer<Integer> a();
		//public native MyStruct a(MyPtr a);
        public MyPtr a() {
            return io.getTypedPointerField(this, 0);
        }
        public MyStruct a(MyPtr a) {
            io.setPointerField(this, 0, a);
            return this;
        }
        //public native void a(MyPtr a);
	}
	
	@Test
	public void testDummyPtrs() {
		int nPtrs = 3;
		Pointer<MyPtr> pptrs = Pointer.allocateTypedPointers(MyPtr.class, nPtrs), pptr = Pointer.allocateTypedPointer(MyPtr.class);
		assertEquals(nPtrs, pptrs.getValidElements());
		assertEquals(nPtrs * Pointer.SIZE, pptrs.getValidBytes());
		assertEquals(1, pptr.getValidElements());
		for (Pointer<MyPtr> ptrs : new Pointer[] { pptr, pptrs }) {;
			ptrs.setSizeT(10);
			MyPtr ptr = ptrs.get();
			assertTrue(ptr instanceof MyPtr);
			assertEquals(10, ptr.getPeer());
		}
	}
	
	@Test
	public void testStructTypedPtrField() {
		MyStruct s = new MyStruct();
        assertNull(s.a());
		Pointer<MyStruct> ps = Pointer.pointerTo(s);
		ps.setSizeT(10);
		MyPtr ptr = s.a();
		assertTrue(ptr instanceof MyPtr);
		assertEquals(10, ptr.getPeer());
	}
	
	@Test
	public void testStringPointer() {
		assertNull(Pointer.pointerToCString(null));
		Pointer<Byte> p = Pointer.pointerToCString("test");
		assertEquals("test", p.getCString());
	}
	
	@Test
	public void testStringsPointer() {
		assertNull(Pointer.pointerToCStrings((String[])null));
		
		Pointer<Pointer<Byte>> p = Pointer.pointerToCStrings(null, null);
		assertNull(p.get(0));
		assertNull(p.get(1));
		
		p = Pointer.pointerToCStrings("test1", "test2");
		assertEquals("test1", p.get(0).getCString());
		assertEquals("test2", p.get(1).getCString());
	}
	
	@Test
	public void testEquals() {
		Pointer m1 = Pointer.allocateBytes(2), m2 = Pointer.allocateBytes(2);
		assertNotNull(m1);
		assertNotNull(m2);
		assertTrue(!m1.equals(m2));
		
		long addr1 = m1.getPeer(), addr2 = m2.getPeer();
		Pointer[] ps1 = new Pointer[] {
			m1,
			new MyPtr(addr1),
			Pointer.pointerToAddress(addr1)
		};
		Pointer[] ps2 = new Pointer[] {
			m2,
			new MyPtr(addr2),
			Pointer.pointerToAddress(addr2)
		};
		for (Pointer p1 : ps1) {
			assertNotNull(p1);
			assertEquals(m1, p1);
			assertEquals(p1, m1);	
		}
		for (Pointer p2 : ps2) {
			assertNotNull(p2);
			assertEquals(m2, p2);
			assertEquals(p2, m2);	
		}
		
		for (Pointer p1 : ps1) {
			for (Pointer p2 : ps2) {
				assertTrue(!p1.equals(p2));
			}	
		}
	}
}

