/*
 * This file is part of the Owl Positioning System (OwlPS) project.
 * It is subject to the copyright notice and license terms in the
 * COPYRIGHT.t2t file found in the top-level directory of this
 * distribution and at
 *   https://code.lm7.fr/mcy/owlps/src/master/COPYRIGHT.t2t
 * No part of the OwlPS Project, including this file, may be copied,
 * modified, propagated, or distributed except according to the terms
 * contained in the COPYRIGHT.t2t file; the COPYRIGHT.t2t file must be
 * distributed along with this file, either separately or by replacing
 * this notice by the COPYRIGHT.t2t file's contents.
 */


#include "result.hh"
#include "request.hh"
#include "area.hh"
#include "stock.hh"
#include "configuration.hh"

#include <sstream>

using namespace std ;



/* *** Constructors *** */


/**
 * The error (distance between _position and _real_position) is
 * computed automatically.
 */
Result::Result(const Request *const _request,
               const std::string &_algorithm,
               const Point3D &_position,
               const Point3D &real_position):
  request(_request), algorithm(_algorithm), position(_position)
{
  compute_error(real_position) ;
}



/* *** Read accessors *** */


string Result::in_which_area() const
{
  const Area *area = Stock::in_which_area_is(position) ;
  if (!area)
    return "" ;

  return area->get_name() ;
}



/* *** Write accessors *** */


void Result::compute_error(const Point3D &real_position)
{
  if (Configuration::bool_value("output.2d-error"))
    error = position.distance_2d(real_position) ;
  else
    error = position.distance(real_position) ;
}



/* *** Operators *** */


Result& Result::operator=(const Result &source)
{
  if (this == &source)
    return *this ;

  request = source.request ;
  algorithm = source.algorithm ;
  position = source.position ;
  error = source.error ;

  return *this ;
}


bool Result::operator==(const Result &source) const
{
  return
    request == source.request &&
    algorithm == source.algorithm &&
    position == source.position &&
    error == source.error ;
}



/**
 * This function creates a CSV string from the Result's data.
 *
 * The format used is the following:
 *   Algorithm_name;X;Y;Z;Error;Area_name
 *
 * @returns The result as a CSV string, *without* a trailing '\\n'.
 */
const string Result::to_csv() const
{
  ostringstream csv_line ;

  csv_line
      << algorithm
      << ';' << position.get_x()
      << ';' << position.get_y()
      << ';' << position.get_z()
      << ';' << error
      << ';' ;

  const Area *const area = Stock::in_which_area_is(position) ;
  if (area)
    csv_line << area->get_name() ;

  return csv_line.str() ;
}



std::ostream& operator<<(ostream &os, const Result &r)
{
  os
      << "The result of the algorithm " << r.algorithm
      << " is: " << r.position
      << " (area: \"" << r.in_which_area() << "\")" ;
  if (r.error >= 0)
    os << ", error = " << r.error << " m" ;
  return os ;
}
