package org.slc.sli.ingestion.landingzone.validation;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Map;

import junit.framework.Assert;

import org.codehaus.jackson.map.ObjectMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import org.slc.sli.domain.Entity;
import org.slc.sli.ingestion.NeutralRecord;
import org.slc.sli.ingestion.NeutralRecordEntity;
import org.slc.sli.ingestion.validation.ErrorReport;

/**
 * Tests good and bad sample Avro schemas for Students.
 *
 * @author Tom Shewchuk <tshewchuk@wgen.net>
 *
 */

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/spring/applicationContext-test.xml" })
public class AvroRecordValidatorTest {

    @Autowired
    private AvroRecordValidator validator;

    @SuppressWarnings("unchecked")
    @Test
    public void testValidStudent() throws Exception {
        BufferedReader reader = new BufferedReader(new FileReader("src/test/resources/student_fixture.json"));

        // Insure each record is valid.
        String student;
        int recordNumber = 0;
        while ((student = reader.readLine()) != null) {
            ObjectMapper oRead = new ObjectMapper();
            Map<String, Object> obj = oRead.readValue(student, Map.class);
            Assert.assertTrue(mapValidation((Map<String, Object>) obj.get("body"), "student", ++recordNumber));
        }
    }

    @SuppressWarnings("unchecked")
    @Test
    public void testInvalidStudent() throws Exception {
        BufferedReader reader = new BufferedReader(new FileReader("src/test/resources/bad_student_fixture.json"));

        // Insure each record is invalid.
        String student;
        int recordNumber = 0;
        while ((student = reader.readLine()) != null) {
            ObjectMapper oRead = new ObjectMapper();
            Map<String, Object> obj = oRead.readValue(student, Map.class);
            Assert.assertFalse(mapValidation((Map<String, Object>) obj.get("body"), "student", ++recordNumber));
        }
    }

    private boolean mapValidation(Map<String, Object> obj, String schemaName, int recordNumber) {

        boolean returnVal;

        ErrorReport errorReport = new TestErrorReport();

        NeutralRecord neutralRecord = new NeutralRecord();
        neutralRecord.setAttributes(obj);
        neutralRecord.setRecordType(schemaName);
        Entity entity = new NeutralRecordEntity(neutralRecord, recordNumber);

        returnVal = validator.isValid(entity, errorReport);

        // Insure each error message is as expected.
        if (returnVal) {
            // Record is valid; insure there are no messages.
            Assert.assertFalse(((TestErrorReport) errorReport).hasErrors());
        } else {
            // Record is invalid; insure messages are as expected.
            Assert.assertTrue(((TestErrorReport) errorReport).hasErrors());
            switch (recordNumber) {
            case 1:
                Assert.assertEquals(((TestErrorReport) errorReport).getMessages().size(), 2);
                Assert.assertEquals(((TestErrorReport) errorReport).getMessages().toArray()[0],
                        "Record 1: Missing or empty field <name.lastSurname>.");
                Assert.assertEquals(((TestErrorReport) errorReport).getMessages().toArray()[1],
                        "Record 1: Unknown field <name.lastSurename>.");
                break;
            case 2:
                Assert.assertEquals(((TestErrorReport) errorReport).getMessages().size(), 1);
                Assert.assertEquals(((TestErrorReport) errorReport).getMessages().toArray()[0],
                        "Record 2: Enumeration mismatch for field <sex> (legal values are [Female, Male]).");
                break;
            case 3:
                Assert.assertEquals(((TestErrorReport) errorReport).getMessages().size(), 1);
                Assert.assertEquals(((TestErrorReport) errorReport).getMessages().toArray()[0],
                        "Record 3: Invalid data type for field <name.firstName> (expected String).");
                break;
            default:
                Assert.fail();
            }
        }

        return returnVal;
    }

}

@@ -3124,16 +3124,20 @@
     
+    
 case 1:%0A
     
@@ -3132,16 +3132,20 @@
 case 1:%0A
+    
         
@@ -3164,32 +3164,35 @@
 rt.assertEquals(
+2, 
 ((TestErrorRepor
@@ -3231,14 +3231,15 @@
 ze()
-, 2
 );%0A
+    
     
@@ -3274,92 +3274,8 @@
 als(
-((TestErrorReport) errorReport).getMessages().toArray()%5B0%5D,%0A                        
 %22Rec
@@ -3320,26 +3320,25 @@
 stSurname%3E.%22
-);
+,
 %0A           
@@ -3342,36 +3342,28 @@
         
-Assert.assertEquals(
+            
 ((TestEr
@@ -3414,11 +3414,12 @@
 y()%5B
-1%5D,
+0%5D);
 %0A   
@@ -3427,36 +3427,52 @@
                 
-    
+Assert.assertEquals(
 %22Record 1: Unkno
@@ -3501,19 +3501,112 @@
 ename%3E.%22
-);%0A
+, ((TestErrorReport) errorReport)%0A                            .getMessages().toArray()%5B1%5D);%0A    
         
@@ -3636,16 +3636,20 @@
     
+    
 case 2:%0A
     
@@ -3644,16 +3644,20 @@
 case 2:%0A
+    
         
@@ -3676,32 +3676,35 @@
 rt.assertEquals(
+1, 
 ((TestErrorRepor
@@ -3731,38 +3731,39 @@
 essages().size()
-, 1
 );%0A
+    
                 
@@ -3786,68 +3786,13 @@
 als(
-((TestErrorReport) errorReport).getMessages().toArray()%5B0%5D,%0A
+%0A    
     
@@ -3898,33 +3898,9 @@
 %5D).%22
-);%0A                break;
+,
 %0A   
@@ -3912,16 +3912,9 @@
     
-case 3:%0A
+ 
     
@@ -3924,37 +3924,16 @@
         
- Assert.assertEquals(
 ((TestEr
@@ -3974,20 +3974,78 @@
 s().
-size(), 1
+toArray()%5B0%5D
 );%0A
+                    break;%0A                case 3:%0A    
     
@@ -4076,16 +4076,19 @@
 tEquals(
+1, 
 ((TestEr
@@ -4129,21 +4129,16 @@
 s().
-toArray()%5B0%5D,
+size());
 %0A   
@@ -4146,36 +4146,52 @@
                 
-    
+Assert.assertEquals(
 %22Record 3: Inval
@@ -4249,19 +4249,111 @@
 tring).%22
-);%0A
+,%0A                            ((TestErrorReport) errorReport).getMessages().toArray()%5B0%5D);%0A    
         
@@ -4379,16 +4379,20 @@
         
+    
 default:
@@ -4392,16 +4392,20 @@
 efault:%0A
+    
         

fix incorrectly ordered assertEquals statements