package nxm.sys.test.junit.libg;

import java.awt.Color;
import java.util.Arrays;

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

/** This will test the MColor class.
    Originally created in response to Bug 1566 to test the toString method
    @author Jim Bauer
    @since NeXtMidas 2.6.1
 */
public final class MColorTest extends NMTestCase {
  /** public constructor to run this JUnit test case outside of NeXtMidas (e.g. Eclipse) */
  public MColorTest (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 MColorTest (String methodName, Midas midas) {
    super(methodName, midas);
  }

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

  /** Empty tests for trivial methods */
  public void testGetColor() {}
  public void testGetColorByIndex() {}

  /** Test the different cases where colors are passed to MColor and a String is returned.
      Initiated by Bug 1566
   */
  public void testToString () {
    Color[] inputColors = {
        Color.black,                    // Case 1 - Known (named) color by name (ex. "black")
        new Color(128, 128, 128, 255),  // Case 2 - Known (named) color by RGBA (ex. 128,128,128,255 "gray")
        new Color(133, 128, 211, 255),  // Case 3 - Non-named OPAQUE color by RGBA (ex. 133, 128, 211, 255)
        new Color(133, 128, 211, 128)   // Case 4 - Non-named Semi-OPAQUE color by RGBA (ex. 133, 128, 211, 128)
    };
    String[] resultStrings = { // expected results
        "black",       // Case 1
        "gray",        // Case 2
        "#8580d3",     // Case 3
        "#808580d3"    // Case 4
    };

    for (int index = 0; index < inputColors.length; index++) {
      String expResult = resultStrings[index];
      String color2String = MColor.toString(inputColors[index]);
      assertEquals("Test toString should be "+expResult, expResult, color2String);
    }
  }

  public void testReverseColorMap () {
    Color[] inputColorsEven = { Color.black, Color.blue, Color.red, Color.yellow, Color.green, Color.white };
    Color[] ExpColorsEven   = { Color.black, Color.white, Color.green, Color.yellow, Color.red, Color.blue };
    Color[] inputColorsOdd  = { Color.black, Color.red, Color.yellow, Color.green, Color.white };
    Color[] ExpColorsOdd    = { Color.black, Color.white, Color.green, Color.yellow, Color.red };

    Color[] tempEven = MColor.reverseColorMap(inputColorsEven);
    assertTrue("Reverse colors for even length array", Arrays.equals(tempEven, ExpColorsEven));

    Color[] tempOdd = MColor.reverseColorMap(inputColorsOdd);
    assertTrue("Reverse colors for odd length array", Arrays.equals(tempOdd, ExpColorsOdd));
  }

  /** Tests passing of colors with alpha components by HEX String to MColor */
  public void testGetLegacyColor () {
    String[] inputStrings = {
        "0x7fffdd11",   // Case 1 - String starts with '0x'
        "#7fffdd11",    // Case 3 - String starts with '#'
        "#ffffdd11",    // Case 4 - String is totally Opaque (Starts with '#ff')
        "0Xffffdd11",   // Case 5 - String is totally Opaque (Starts with '0Xff')
        "#00ffdd11",    // Case 6 - String is totally Transparent (Starts with '#00')
        "0X00ffdd11"    // Case 7 - String is totally transparent (Starts with '0X00')
    };
    String[] resultStrings = { // expected result HEX strings
        "#7fffdd11", // Case 1
        "#7fffdd11", // Case 3
        "#ffdd11",   // Case 4
        "#ffdd11",   // Case 5
        "#00ffdd11", // Case 6
        "#00ffdd11"  // Case 7
    };

    for (int ii = 0; ii < inputStrings.length; ii++) {
      Color color = MColor.getColor(inputStrings[ii]); // convert the String to a Color
      String color2String = MColor.toString(color);    // Convert it back to a String
      String expResult = resultStrings[ii];
      assertEquals("Color hex string should be '"+expResult+"'", expResult, color2String);
    }
  }

  /** @since 3.5.0 */
  public void testColorDifference () {
    Color[] testInputPairs = new Color[] {
        Color.black,     Color.white,         // #1
        Color.gray,      Color.lightGray,     // #2
        Color.gray,      Color.darkGray,      // #3
        Color.lightGray, Color.darkGray,      // #4
        Color.pink,      Color.cyan,          // #5
        Color.pink,      Color.magenta,       // #6
        Color.pink,      Color.red,           // #7
        Color.blue,      Color.green,         // #8
        Color.blue,      Color.blue.darker(), // #9
    };
    double[] expColorDiffs = new double[] {
        1.0,      // #1 black,     white
        0.250980, // #2 gray,      lightGray
        0.250980, // #3 gray,      darkGray
        0.501960, // #4 lightGray, darkGray
        0.631624, // #5 pink,      cyan
        0.435659, // #6 pink,      magenta
        0.560340, // #7 pink,      red
        0.816496, // #8 blue,      green
        0.174337, // #9 blue,      blue.darker()
    };

    final double tolerance = 0.000001;
    for (int ii=0; ii<testInputPairs.length; ii+=2) {
      Color color1 = testInputPairs[ii];
      Color color2 = testInputPairs[ii+1];
      double color1Diff  = MColor.colorDifference(color1, color1);
      double color12Diff = MColor.colorDifference(color1, color2);
      double color21Diff = MColor.colorDifference(color2, color1);
      assertEquals("Same color difference is zero for " + color1, 0.0, color1Diff, 0.0);
      assertEquals("color 1,2 difference for " + color1 + " , " + color2, expColorDiffs[ii/2], color12Diff, tolerance);
      assertEquals("color 2,1 difference for " + color2 + " , " + color1, expColorDiffs[ii/2], color21Diff, tolerance);
    }
  }
}
