/**
   * Analyzes an image taken by the Axis Camera, performing various functions to determine where the
   * goal is and at what goal the robot is facing
   *
   * @param
   * @return Array of doubles where the first value is the type of goal (2.0 high, 1.0 middle, 0.0
   *     no goal), the x-centered-normalized value, the y-centered-normalized value and the
   *     distance. If the distance is negative, no goal was found.
   */
  public double[] analyze() {
    double[] data = new double[3];
    // [goal type, x-centered, y-centered, distance]

    try {
      ColorImage image = camera.getImage(); // Get image from camera
      BinaryImage thresholdImage;
      thresholdImage =
          image.thresholdHSV(120, 120, 44, 80, 98, 100); // "Look" for objects in this HSV range
      BinaryImage convexHullImage = thresholdImage.convexHull(false); // Fill in occluded rectangles
      BinaryImage filteredImage =
          convexHullImage.particleFilter(collection); // Find filled in rectangles

      Scores scores[] = new Scores[filteredImage.getNumberParticles()];

      for (int i = 0; i < scores.length; i++) {
        ParticleAnalysisReport report =
            filteredImage.getParticleAnalysisReport(i); // Get the report for each particle found
        scores[i] = new Scores();

        scores[i].rectangularity = scoreRectangularity(report);
        scores[i].aspectRatioOuter = scoreAspectRatio(filteredImage, report, i, true);
        scores[i].aspectRatioInner = scoreAspectRatio(filteredImage, report, i, false);
        scores[i].xEdge = scoreXEdge(thresholdImage, report);
        scores[i].yEdge = scoreYEdge(thresholdImage, report);

        if (scoreCompare(scores[i], false)) {
          double dist = computeDistance(thresholdImage, report, i, false);
          System.out.println(
              "particle: "
                  + i
                  + " is a High Goal  centerX: "
                  + report.center_mass_x_normalized
                  + "centerY: "
                  + report.center_mass_y_normalized);
          System.out.println("Distance: " + dist);
          data[0] = 2.0;
          data[1] = report.center_mass_x_normalized;
          data[2] = report.center_mass_y_normalized;
          data[3] = dist;
        } else if (scoreCompare(scores[i], true)) {
          double dist = computeDistance(thresholdImage, report, i, false);
          System.out.println(
              "particle: "
                  + i
                  + " is a Middle Goal  centerX: "
                  + report.center_mass_x_normalized
                  + "centerY: "
                  + report.center_mass_y_normalized);
          System.out.println("Distance: " + dist);
          data[0] = 1.0;
          data[1] = report.center_mass_x_normalized;
          data[2] = report.center_mass_y_normalized;
          data[3] = dist;
        } else {
          System.out.println(
              "particle: "
                  + i
                  + " is not a goal  centerX: "
                  + report.center_mass_x_normalized
                  + "centerY: "
                  + report.center_mass_y_normalized);
          data[0] = 0.0;
          data[1] = report.center_mass_x_normalized;
          data[2] = report.center_mass_y_normalized;
          data[3] = -1.0;
        }
        System.out.println(
            "rect: " + scores[i].rectangularity + "ARinner: " + scores[i].aspectRatioInner);
        System.out.println(
            "ARouter: "
                + scores[i].aspectRatioOuter
                + "xEdge: "
                + scores[i].xEdge
                + "yEdge: "
                + scores[i].yEdge);
      }

      /* MUST USE FREE FUNCTION: all images are currently allocated in C structures */
      filteredImage.free();
      convexHullImage.free();
      thresholdImage.free();
      image.free();
    } // end analyze()
    catch (AxisCameraException e) {
      data[0] = 0.0;
      data[1] = 0.0;
      data[2] = 0.0;
      data[3] = -1.0;
      SmartDashboard.putString("ERROR: ", "Camera malfunction!");
    } catch (NIVisionException ex) {
      data[0] = 0.0;
      data[1] = 0.0;
      data[2] = 0.0;
      data[3] = -1.0;
      SmartDashboard.putString("ERROR: ", "NIVision Exception!");
    }

    return data;
  }
  public TargetScores[] visionAnalyze() {
    // TargetScores[] tScores_Out;// = new TargetScores[1][];
    TargetScores[] tScores = null;
    try {
      /**
       * Do the image capture with the camera and apply the algorithm described above. This sample
       * will either get images from the camera or from an image file stored in the top level
       * directory in the flash memory on the cRIO. The file name in this case is "testImage.jpg"
       */
      ColorImage image = camera.getImage(); // comment if using stored images
      // ColorImage image;                           // next 2 lines read image from flash on cRIO
      // image = new RGBImage("/testImage.jpg");		// get the sample image from the cRIO flash
      BinaryImage thresholdImage =
          image.thresholdHSV(60, 100, 90, 255, 20, 255); // keep only red objects
      // thresholdImage.write("/threshold.bmp");
      BinaryImage convexHullImage = thresholdImage.convexHull(false); // fill in occluded rectangles
      // convexHullImage.write("/convexHull.bmp");
      BinaryImage filteredImage = convexHullImage.particleFilter(cc); // filter out small particles
      // filteredImage.write("/filteredImage.bmp");

      // iterate through each particle and score to see if it is a target
      Scores scores[] = new Scores[filteredImage.getNumberParticles()];
      tScores = new TargetScores[filteredImage.getNumberParticles()];
      for (int i = 0; i < scores.length; i++) {

        ParticleAnalysisReport report = filteredImage.getParticleAnalysisReport(i);
        scores[i] = new Scores();
        tScores[i] = new TargetScores();

        scores[i].rectangularity = scoreRectangularity(report);
        scores[i].aspectRatioOuter = scoreAspectRatio(filteredImage, report, i, true);
        scores[i].aspectRatioInner = scoreAspectRatio(filteredImage, report, i, false);
        scores[i].xEdge = scoreXEdge(thresholdImage, report);
        scores[i].yEdge = scoreYEdge(thresholdImage, report);

        if (scoreCompare(scores[i], false)) {
          tScores[i].goal = TargetScores.high;
        } else if (scoreCompare(scores[i], true)) {
          tScores[i].goal = TargetScores.med;
        }
        tScores[i].yVal = report.center_mass_y;
        tScores[i].xVal = report.center_mass_x;
        tScores[i].yValAim = axisToAim('y', tScores[i].yVal);
        /*
                         if(scoreCompare(scores[i], false))
                         {
                             System.out.println("particle: " + i + "is a High Goal  centerX: " + report.center_mass_x_normalized + "centerY: " + report.center_mass_y_normalized);
        System.out.println("Distance: " + computeDistance(thresholdImage, report, i, false));
                         } else if (scoreCompare(scores[i], true)) {
        System.out.println("particle: " + i + "is a Middle Goal  centerX: " + report.center_mass_x_normalized + "centerY: " + report.center_mass_y_normalized);
        System.out.println("Distance: " + computeDistance(thresholdImage, report, i, true));
                         } else {
                             System.out.println("particle: " + i + "is not a goal  centerX: " + report.center_mass_x_normalized + "centerY: " + report.center_mass_y_normalized);
                         }
        System.out.println("rect: " + scores[i].rectangularity + "ARinner: " + scores[i].aspectRatioInner);
        System.out.println("ARouter: " + scores[i].aspectRatioOuter + "xEdge: " + scores[i].xEdge + "yEdge: " + scores[i].yEdge);

                         */

      }

      /**
       * all images in Java must be freed after they are used since they are allocated out of C data
       * structures. Not calling free() will cause the memory to accumulate over each pass of this
       * loop.
       */
      filteredImage.free();
      convexHullImage.free();
      thresholdImage.free();
      image.free();

      // tScores_Out = new TargetScores[tScores.length];
      // tScores_Out = (TargetScores[])tScores.clone();

      // myScores = scores;

    } catch (AxisCameraException ex) { // this is needed if the camera.getImage() is called
      ex.printStackTrace();
    } catch (NIVisionException ex) {
      ex.printStackTrace();
    }
    if (tScores == null) {
      tScores = new TargetScores[1];
      tScores[1] = new NoScores();
    }
    return tScores; // tScores_Out;
  }