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

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import static net.ranides.assira.junit.NewAssert.*;
import net.ranides.assira.text.Wildcard;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class SerializationUtilsTest {
	
	@Test
	public void testCopy() throws IOException {
		List<Integer> a = new ArrayList<>(Arrays.asList(1,2,3,4));
		List<Integer> b = SerializationUtils.copy(a);
		
		assertEquals(a,b);
		assertEquals(a.getClass(),b.getClass());
	}
	
	@Test
	public void testSizeOf() throws IOException {
		List<Integer> a1 = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7,8));
		List<Integer> a2 = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16));
		List<Float> b1 = new ArrayList<>(Arrays.asList(1.f, 2.f, 3.f, 4.f));
		List<Float> b2 = new ArrayList<>(Arrays.asList(1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f));
		List<String> c1 = new ArrayList<>(Arrays.asList("T1", "T2", "T3", "T4", "T5", "T6", "T7", "T8"));
		List<String> c2 = new ArrayList<>(Arrays.asList(
			"T1....................................1",
			"T2....................................2",
			"T3....................................3",
			"T4....................................4",
			"T5....................................5",
			"T6....................................6",
			"T7....................................7",
			"T8....................................8"
		));
		SerializationUtils.SizeInfo ia1 =  SerializationUtils.sizeof(a1);
		SerializationUtils.SizeInfo ia2 =  SerializationUtils.sizeof(a2);
		SerializationUtils.SizeInfo ib1 =  SerializationUtils.sizeof(b1);
		SerializationUtils.SizeInfo ib2 =  SerializationUtils.sizeof(b2);
		SerializationUtils.SizeInfo ic1 =  SerializationUtils.sizeof(c1);
		SerializationUtils.SizeInfo ic2 =  SerializationUtils.sizeof(c2);
		
//        System.out.printf("a1 %s%n", ia1);
//        System.out.printf("a2 %s%n", ia2);
//        System.out.printf("b1 %s%n", ib1);
//        System.out.printf("b2 %s%n", ib2);
//        System.out.printf("c1  %s%n", ic1);
//        System.out.printf("c2  %s%n", ic2);

        assertTrue(Wildcard.match("SizeOf{ size=*, element=*, overhead=* }", ia1.toString()));
        
		assertTrue( ia1.size() < ia2.size());
		assertTrue( ia1.element() == ia2.element());
		
		assertTrue( ib1.size() < ib2.size());
		assertTrue( ib1.element() == ib2.element());
		
		assertTrue( ic1.size() < ic2.size());
		assertTrue( ic1.element()< ic2.element());
	}
    
    @Test
    public void testProxy() throws IOException {
        MyValue0 a = SerializationUtils.copy(new MyValue0("x", "22"));
        MyValue0 b = SerializationUtils.copy(new MyValue1("x", "22"));
        MyValue0 c = SerializationUtils.copy(new MyValue2("x", "22"));
        MyValue0 d = SerializationUtils.copy(new MyValue3("x", "22"));
        
        assertEquals("null : null", a.toString());
        assertEquals("x : 22", b.toString());
        assertEquals("x! : 22??", c.toString());
        assertEquals("null : null", d.toString());
        
        
    }
    
    @SuppressWarnings("PMD")
    @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED")
    private static class MyValue0 implements Serializable {
        
        private static final long serialVersionUID = 1L;
        
        transient final String a;
        transient final String b;

        public MyValue0(String a, String b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public String toString() {
            return a + " : " + b;
        }
        
    }
    
    private static class MyValue1 extends MyValue0 {
        
        public MyValue1(String a, String b) {
            super(a, b);
        }
        
        private Object writeReplace() {
            return SerializationUtils.proxy(this, a, b);
        }
        
    }
    
    private static class MyValue2 extends MyValue1 {
        
        public MyValue2(String a, String b) {
            super(a, b+"?");
        }

        private Object writeReplace() {
            return SerializationUtils.proxy(this, a+"!", b);
        }
    }
    
    private static class MyValue3 extends MyValue1 {
        
        public MyValue3(String a, String b) {
            super(a, b+"?");
        }

    }
	
}
