package eu.dnetlib.espas.data.harvest;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;

import org.junit.Test;

public class TestBoundingBox
{
   @Test
   public void testEqualsWithFullyPopulatedBoundingBoxObjects()
   {
      BoundingBox expected = new BoundingBox();
      expected.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      expected.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      expected.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      BoundingBox actual = new BoundingBox();
      actual.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      actual.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      actual.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      assertEquals("These bounding boxes should be equal.", expected, actual);
   }

   @Test
   public void testEqualsWithPartiallyPopulatedBoundingBoxObjects1()
   {
      BoundingBox expected = new BoundingBox();
      expected.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      expected.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      BoundingBox actual = new BoundingBox();
      actual.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      actual.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      assertEquals("These bounding boxes should be equal.", expected, actual);
   }

   @Test
   public void testEqualsWithPartiallyPopulatedBoundingBoxObjects2()
   {
      BoundingBox expected = new BoundingBox();
      expected.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      expected.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      BoundingBox actual = new BoundingBox();
      actual.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      actual.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      assertEquals("These bounding boxes should be equal.", expected, actual);
   }

   @Test
   public void testEqualsWithPartiallyPopulatedBoundingBoxObjects3()
   {
      BoundingBox expected = new BoundingBox();
      expected.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      expected.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      BoundingBox actual = new BoundingBox();
      actual.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      actual.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      assertEquals("These bounding boxes should be equal.", expected, actual);
   }

   @Test
   public void testEqualsWithPartiallyPopulatedBoundingBoxObjects4()
   {
      BoundingBox expected = new BoundingBox();
      expected.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      expected.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      BoundingBox actual = expected;
      assertEquals("These bounding boxes should be equal.", expected, actual);
   }

   // Test 8 different cases.
   // if(null != this.bbAttributes && !(equals = equals && this.bbAttributes.equals(bbBoundingBox.getBbAttributes())))
   @Test
   public void testNotEqualWithFullyPopulatedBoundingBoxObjects1()
   {
      BoundingBox expected = null;
      BoundingBox actual = new BoundingBox();
      actual.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_2");
      actual.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      actual.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      assertFalse("These bounding boxes should not be equal.", actual.equals(expected));

      expected = new BoundingBox();
      expected.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      expected.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      expected.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      assertFalse("These bounding boxes should not be equal.", expected.equals(actual));

      actual = null;
      assertFalse("These bounding boxes should not be equal.", expected.equals(actual));
   }

   @Test
   public void testNotEqualWithFullyPopulatedBoundingBoxObjects2()
   {
      BoundingBox expected = new BoundingBox();
      expected.setBbAttributes(null);
      expected.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      expected.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      BoundingBox actual = new BoundingBox();
      actual.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_2");
      actual.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      actual.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      assertFalse("These bounding boxes should not be equal.", expected.equals(actual));
   }

   @Test
   public void testNotEqualWithFullyPopulatedBoundingBoxObjects3()
   {
      BoundingBox expected = new BoundingBox();
      expected.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      expected.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      expected.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      BoundingBox actual = null;
      assertFalse("These bounding boxes should not be equal.", expected.equals(actual));
   }

   // Different sizes of lower corner spatial arrays.
   @Test
   public void testNotEqualWithFullyPopulatedBoundingBoxObjects4()
   {
      BoundingBox expected = new BoundingBox();
      expected.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      expected.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      expected.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      BoundingBox actual = new BoundingBox();
      actual.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      actual.setBBLowerCorner(new double[]{10.001, 20.001, 30.001, 40.001});
      actual.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      assertFalse("These bounding boxes should not be equal.", expected.equals(actual));
   }

   // Different sizes of upper corner spatial arrays.
   @Test
   public void testNotEqualWithFullyPopulatedBoundingBoxObjects5()
   {
      BoundingBox expected = new BoundingBox();
      expected.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      expected.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      expected.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      BoundingBox actual = new BoundingBox();
      actual.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      actual.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      actual.setBBUpperCorner(new double[]{11.001, 21.001, 31.001, 41.001});
      assertFalse("These bounding boxes should not be equal.", expected.equals(actual));
   }

   // Different value at some point of the lower conrner.
   @Test
   public void testNotEqualWithFullyPopulatedBoundingBoxObjects6()
   {
      BoundingBox expected = new BoundingBox();
      expected.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      expected.setBBLowerCorner(new double[]{10.001, 20.001, 30.001}); // <--- The second value is different.
      expected.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      BoundingBox actual = new BoundingBox();
      actual.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      actual.setBBLowerCorner(new double[]{10.001, 22.001, 30.001});  // <--- The second value is different.
      actual.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      assertFalse("These bounding boxes should not be equal.", expected.equals(actual));
   }

   // Different value at some point of the upper conrner.
   @Test
   public void testNotEqualWithFullyPopulatedBoundingBoxObjects7()
   {
      BoundingBox expected = new BoundingBox();
      expected.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      expected.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      expected.setBBUpperCorner(new double[]{11.001, 21.001, 31.001}); // <--- The 3 value is different.
      BoundingBox actual = new BoundingBox();
      actual.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      actual.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      actual.setBBUpperCorner(new double[]{11.001, 21.001, 32.001}); // <--- The 3 value is different.
      assertFalse("These bounding boxes should not be equal.", expected.equals(actual));
   }

   @Test
   public void testNotEqualWithFullyPopulatedBoundingBoxObjects8()
   {
      BoundingBox expected = new BoundingBox();
      expected.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      expected.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      expected.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      BoundingBox actual = new BoundingBox();
      actual.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      actual.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      actual.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});

      // 1 ) Left lower corner is null, the right lower corner is not null.
      expected.setBBLowerCorner(null);
      assertFalse("These bounding boxes should not be equal.", expected.equals(actual));

      // 2 ) Left lower corner is null, the right lower is null.
      expected.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      actual.setBBLowerCorner(null);
      assertFalse("These bounding boxes should not be equal.", expected.equals(actual));
   }

   @Test
   public void testNotEqualWithFullyPopulatedBoundingBoxObjects9()
   {
      BoundingBox expected = new BoundingBox();
      expected.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      expected.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      expected.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});
      BoundingBox actual = new BoundingBox();
      actual.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "bounding_box_crs_1");
      actual.setBBLowerCorner(new double[]{10.001, 20.001, 30.001});
      actual.setBBUpperCorner(new double[]{11.001, 21.001, 31.001});

      // 1 ) Left upper corner is null, the right upper corner is not null.
      expected.setBBUpperCorner(null);
      assertFalse("These bounding boxes should not be equal.", expected.equals(actual));

      // 2 ) Left upper corner is null, the right upper is null.
      expected.setBBUpperCorner(new double[]{10.001, 20.001, 30.001});
      actual.setBBUpperCorner(null);
      assertFalse("These bounding boxes should not be equal.", expected.equals(actual));
   }

   @Test
   public void testToString()
   {
      String expected = "<ows:BoundingBox crs=\"urn:x-ogc:def:crs:EPSG:6.11:4326\">" +
		                     "<ows:LowerCorner>60.042 13.754</ows:LowerCorner>" +
		                     "<ows:UpperCorner>68.410 17.920</ows:UpperCorner>" +
		                  "</ows:BoundingBox>";
      BoundingBox boundingBox = new BoundingBox();
      boundingBox.put(BoundingBox.BB_CRS_ELEMENT_ATTRIBUTE, "urn:x-ogc:def:crs:EPSG:6.11:4326");
      boundingBox.setBBLowerCorner(new double[]{60.042, 13.754});
      boundingBox.setBBUpperCorner(new double[]{68.410, 17.920});
      assertEquals("These string-xml serializations should be equal.", expected, boundingBox.toString());
   }
}
