// Finds the distance to post
// Tunes the BBox using higher resolution foveas
RRCoord GoalDetection::findDistanceToPost(VisionFrame &frame,
                                          const Fovea& fovea,
                                          BBox& goal,
                                          int numPosts,
                                          PostInfo& p) {

   bool trustDistance = true;
   float differenceThreshold = 1.7;

   // **** Try finding the distance using kinematics of the base ****
   findBaseOfPost(frame, goal);

   const CameraToRR *convRR = &frame.cameraToRR;
   Point base = Point((goal.a.x()+goal.b.x())/2, goal.b.y());
   RRCoord rr = convRR->convertToRR(base, false);
   float kdistance = rr.distance();
   
   // **** Try using the width the find the distance ****
   // Calculate width distance at 3 points and take median
   std::map<float, float> distances;
   for (float h = 0.89; h < 1; h += 0.05) {
      float d = widthDistanceToPost(frame, goal, h);
      distances.insert(std::make_pair(d,h));
   }
   std::map<float, float>::iterator i = distances.begin();
   if (distances.size() > 1) ++i;
   float wdistance = widthDistanceToPost(frame, goal, i->second, true);

   // **** Decide which distance to use ****
   // Kinematics is usually more accurate, so use it unless we know it's wrong

   // If post ends at bottom of image, probably not the bottom, so use width
   bool width = false;
   if (fovea.top && goal.b.y() > (TOP_IMAGE_ROWS-10)) {
      width = true;
   }

   // If still yellow below the base, probably missed the bottom, so use width
   // Only for 1 post though
   if (numPosts == 1) {
      Point fTop = fovea.mapImageToFovea(goal.a);
      Point fBot = fovea.mapImageToFovea(goal.b);
      const YHistogram &yhistogram = fovea.yhistogram;
      int height = (fBot.y() - fTop.y()) / 4; // set max scan size
      int endPoint = std::min(fovea.bb.height(), fBot.y() + height);
      int noYellow = fBot.y();

      for (int i = fBot.y(); i < endPoint; ++i) {
         int current = yhistogram._counts[i][cGOAL_YELLOW];
         if (current < 10) noYellow = i;
      }
      if (noYellow == fBot.y()) trustDistance = false;
   }
   
   // Decided to use width distance
   if (width) {
      if (wdistance < 1500) rr.distance() = wdistance;
      else trustDistance = false;
//      differenceThreshold = 1.7;
   }

   // Check that kinematics and width distances are similar
   else if (kdistance < 2500) {
   }

   else if (((kdistance / wdistance) > differenceThreshold) ||
       ((wdistance / kdistance) > differenceThreshold)) {
      trustDistance = false;
   }

   // Check distance is reasonable
   if (rr.distance() > 12000) {
      trustDistance = false;
      rr.distance() = 12000;
   }

   // Set variables in PostInfo
   p.rr = rr;
   p.kDistance = kdistance;
   p.wDistance = wdistance;
   p.trustDistance = trustDistance;
   p.imageCoords = goal;

   return rr;
}
void GoalDetection::performSanityChecks(const Fovea &fovea,
                                        const VisionFrame &frame,
                                        std::vector<BBox> &regions) {
   std::vector<BBox> candidates (regions);
   regions.clear();
   std::vector<BBox>::iterator it;
   for (it = candidates.begin(); it != candidates.end(); ++it) {

      // Check that the middle and the bottom 75% for edges
      // Only need 1 strong edge in each to be good

      int middle = (it->a.y() + it->b.y()) / 2;
      int bottom = it->a.y() + (it->b.y() - it->a.y()) * 0.75;
      bool keepM = false;
      bool keepB = false;
      for (int col = it->a.x(); col <= it->b.x(); ++col) {
         
         // Check middle
         Point edge = fovea.edge(col, middle);
         float magnitude = (edge.x() * edge.x()) + (edge.y() * edge.y());
         if (magnitude > MIN_EDGE_THRESHOLD) keepM = true;

         // Check bottom
         edge = fovea.edge(col, bottom);
         magnitude = (edge.x() * edge.x()) + (edge.y() * edge.y());
         if (magnitude > MIN_EDGE_THRESHOLD) keepB = true;
      }
      if (!keepM) {
         //std::cout << "throwing away since no keepM" << std::endl;
         continue              ;
      }
      if (!keepB) {
         //std::cout << "throwing away since no keepB" << std::endl;
         continue;
      }

      // Check % of colour in goal post - ie compare length and colour
      float length = it->b.y() - it->a.y();
      int centre = (it->a.x() + it->b.x()) / 2;
      float numColourPixels = 0;
      for (int row = it->a.y(); row < it->b.y(); ++row) {
         if (fovea.colour(centre, row) == cGOAL_YELLOW) {
            ++numColourPixels;
         }
      }

      if ((numColourPixels / length) < COLOUR_RATIO_THRESHOLD) {
         //std::cout << "throwing away since not enough colour" << std::endl;
         continue;
      }

      // Check bottom of goal post is below field edge
      Point fieldEdge = fovea.mapFoveaToImage(Point(centre, 0));
      int fieldEdgeY = 0;
      if (fovea.top) {
         fieldEdgeY = frame.topStartScanCoords[fieldEdge.x()];
      } else {
         fieldEdgeY = frame.botStartScanCoords[fieldEdge.x()];
      }
      fieldEdge.y() = std::max(fieldEdge.y(), fieldEdgeY);
      fieldEdge = fovea.mapImageToFovea(fieldEdge);

      if (fieldEdge.y() > it->b.y()) {
         //std::cout << "throwing away since above field edge" << std::endl;
         continue;
      }

      regions.push_back(*it);
   }

   // If more than 2 goals, things have gone wrong, so panic
   if (regions.size() > 2) regions.clear();
}