package nxm.sys.test.junit.libg;

import nxm.sys.lib.Midas;
import nxm.sys.libg.Layer;
import nxm.sys.test.junit.NMTestCase;


  /** This will test the Layer inner class SlidingMinMax.
  Originally created in response to Bug 2012 to use the test method
  testSlidingMinMax to test the SlidingMinMax class
  @author Jeanette McCallr
  @version $Id: LayerTest.java,v 1.3 2015/10/02 13:43:33 jtm Exp $
  @since NeXtMidas 3.7.0
*/
public final class LayerTest extends NMTestCase {
/** public constructor to run this JUnit test case outside of NeXtMidas (e.g. Eclipse) */
public LayerTest (String methodName) { this(methodName, null); }

/** Creates a new instance of the class.
    @param methodName The name of the method being called.
    @param midas      The midas context testTo use when running the tests.
 */
public LayerTest (String methodName, Midas midas) {
  super(methodName, midas);
}

//////////////////////////////////////////////////////////////////////////////


  /** Test the SlidingMinMax class via the InternalUseOnly test method in Layer
      Initiated by Bug 2901

      Note: The tests were designed to exercise a variety of paths (full recalculation
      and not).  Verification that full recalculation was only done when needed was
      achieved by enabling the  debug println statements in testSlidingMinMax and
      the SlidingMinMax methods recalculateSmallestMinAndIndex and recalculatedLargetsMaxAndIndex.
   */
  public void testTestSlidingMinMax () {
    int colMin = 0;
    int colMax = 1;
    double[][] minMaxValues = {
        // 0            1            2            3           4             5            6           7
        {-1,1},      {-20,2},     {-3,30},     {-4,4},      {-5,0.5},    {-0.6,6},    {-7,0.7},    {-80,80},
        {-9,0.9},    {-10,10},    {-11,1.1},   {-120,12},   {-1.3,13},   {-14,1.4},   {-1.5,15},   {-16,16},
        {-1.7,1.7},  {-18,-1.8},  {-1.9,1.9},  {-2.0,2.0},  {-2.1,2.1}
    };
    int buffLength = 8;

    // Test: have not wrapped smallest min and largest max in range
    int autoL = 6;
    int indexResetAutoL = 40; // never
    int newAutoL = -1;        // not used
    int reportIndex = 6;
    // expected to include indexes 1 - 6 (and no full recalculations)
    double[] expected = {-20,30};
    double[] smallestMinLargestMax = Layer.testSlidingMinMax(buffLength, autoL, indexResetAutoL, newAutoL, minMaxValues, reportIndex);
    assertEquals("SlidingMinMax no wrap test, smallest Min",expected[colMin],smallestMinLargestMax[colMin]);
    assertEquals("SlidingMinMax no wrap test, largest Max",expected[colMax],smallestMinLargestMax[colMax]);

    // Test: autoLength=bufferLength and have wrapped and largest max has just been written over
    autoL = 8;
    indexResetAutoL = 40; // never
    newAutoL = -1;        // not used
    reportIndex = 15;
    // expected to include indexes 8 - 15 (and full recalculation of largest max at index 15/7))
    expected[colMin] = -120;
    expected[colMax] = 16;
    smallestMinLargestMax = Layer.testSlidingMinMax(buffLength, autoL, indexResetAutoL, newAutoL, minMaxValues, reportIndex);
    assertEquals("SlidingMinMax largest max just overwritten, smallest Min",expected[colMin],smallestMinLargestMax[colMin]);
    assertEquals("SlidingMinMax largest max just overwritten, largest Max",expected[colMax],smallestMinLargestMax[colMax]);


    // Test: have wrapped and largest max at end of buffer but within range
    autoL = 6;
    indexResetAutoL = 40; // never
    newAutoL = -1;        // not used
    reportIndex = 12;
    // expected to include indexes 7 - 12 (and no full recalculations)
    expected[colMin] = -120;
    expected[colMax] = 80;
    smallestMinLargestMax = Layer.testSlidingMinMax(buffLength, autoL, indexResetAutoL, newAutoL,  minMaxValues, reportIndex);
    assertEquals("SlidingMinMax wrapped and largest max at end of buffer, smallest Min",expected[colMin],smallestMinLargestMax[colMin]);
    assertEquals("SlidingMinMax wrapped and largest max at end of buffer, largest Max",expected[colMax],smallestMinLargestMax[colMax]);

    // Test: only 1 value added
    autoL = 6;
    indexResetAutoL = 40; // never
    newAutoL = -1;        // not used
    reportIndex = 0;
    // expected to only includes index 0 (and obviously no full recalculations)
    expected[colMin] = -1;
    expected[colMax] = 1;
    smallestMinLargestMax = Layer.testSlidingMinMax(buffLength, autoL, indexResetAutoL, newAutoL, minMaxValues, reportIndex);
    assertEquals("SlidingMinMax only 1 value added, smallest Min",expected[colMin],smallestMinLargestMax[colMin]);
    assertEquals("SlidingMinMax only 1 value added, largest Max",expected[colMax],smallestMinLargestMax[colMax]);

    // Test: with auto length change that affects min and max (recalculation forced due to longer autoscale length)
    autoL = 2;
    indexResetAutoL = 6;
    newAutoL = 6;
    reportIndex = 6;
    // expected to include indexes 1 - 6
    // (and smallest min fully recalculated at index 3 because index 1 now out of range,
    // and largest max fully recalculated at index 4 because index 2 now out of range,
    // and full recalculation of both at index 6 due to autoscale length getting longer)
    expected[colMin] = -20;
    expected[colMax] = 30;
    smallestMinLargestMax = Layer.testSlidingMinMax(buffLength, autoL, indexResetAutoL, newAutoL, minMaxValues, reportIndex);
    assertEquals("SlidingMinMax auto length change that affects min and max, smallest Min",expected[colMin],smallestMinLargestMax[colMin]);
    assertEquals("SlidingMinMax auto length change that affects min and max, largest Max",expected[colMax],smallestMinLargestMax[colMax]);

    // Test: same test as auto length change WITHOUT reset
    autoL = 2;
    indexResetAutoL = 40; // never
    newAutoL = 6;
    reportIndex = 6;
    // expected to include indexes 5 - 6
    // (and smallest min fully recalculated at index 3 because index 1 now out of range,
    // and largest max fully recalculated at index 4 because index 2 now out of range)
    expected[colMin] = -7;
    expected[colMax] = 6;
    smallestMinLargestMax = Layer.testSlidingMinMax(buffLength, autoL, indexResetAutoL, newAutoL, minMaxValues, reportIndex);
    assertEquals("SlidingMinMax no auto length change, smallest Min",expected[colMin],smallestMinLargestMax[colMin]);
    assertEquals("SlidingMinMax no auto length change, largest Max",expected[colMax],smallestMinLargestMax[colMax]);

    // Test: with auto length change that affects only min (max still in range)
    autoL = 6;
    indexResetAutoL = 6;
    newAutoL = 5;
    reportIndex = 6;
    // expected to include indexes 2 - 6 (and smallest min recalculated at index 6)
    expected[colMin] = -7;
    expected[colMax] = 30;
    smallestMinLargestMax = Layer.testSlidingMinMax(buffLength, autoL, indexResetAutoL, newAutoL, minMaxValues, reportIndex);
    assertEquals("SlidingMinMax auto length change that affects only min, smallest Min",expected[colMin],smallestMinLargestMax[colMin]);
    assertEquals("SlidingMinMax auto length change that affects only min, largest Max",expected[colMax],smallestMinLargestMax[colMax]);

    // Test: shows capping of autoL to buffer size and recalculation - no recalculation forced for new autoL - but max recalculated when last value added
    autoL = 9;
    indexResetAutoL = 20;
    newAutoL = 5;
    reportIndex = 20;
    // expected to include indexes 5 - 20
    // (and largest max fully recalculated at index 15/7 because old index 7 overwritten / out of range,
    // and smallest min fully recalculated at index 19/3 because index 11/3 now out of range,
    // and largest max fully recalculated at index 20/4 because index 15/7 now out of range due to addition of latest value)
    expected[colMin] = -18;
    expected[colMax] = 2.1;
    smallestMinLargestMax = Layer.testSlidingMinMax(buffLength, autoL, indexResetAutoL, newAutoL, minMaxValues, reportIndex);
    assertEquals("SlidingMinMax capping of autoL to buffer size, smallest Min",expected[colMin],smallestMinLargestMax[colMin]);
    assertEquals("SlidingMinMax capping of autoL to buffer size, largest Max",expected[colMax],smallestMinLargestMax[colMax]);
  }

}
