/*
 * 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 "building.hh"
#include "area.hh"
#include "waypoint.hh"
#include "stock.hh"
#include "posexcept.hh"


using namespace std ;



/* *** Constructors *** */


/**
 * Note: deletes (unallocates) all elements in #areas; deletes elements
 * in #waypoints that belong only to this Building (waypoints that link
 * several buildings are preserved).
 */
Building::~Building()
{
  // Empty Area list
  for (auto i = areas.begin() ; i != areas.end() ; ++i)
    delete i->second ;
  areas.clear() ;

  // Empty Waypoint list
  for (auto i = waypoints.begin() ; i != waypoints.end() ; ++i)
    Stock::waypoint_remove_building(**i, this) ;
  waypoints.clear() ;
}



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


/**
 * If `area` is null, nothing is done.
 * If `area` is a pointer to an Area that is already stored in #areas,
 * nothing is done.
 * If `area` has the same name as (but is not identical to) an Area that
 * is already stored in #areas, an exception is thrown.
 *
 * @param area A pointer to the Area to add.
 * @throws element_already_exists
 */
void Building::add_area(const Area *const area)
{
  if (!area)
    return ;

  string area_name = area->get_name() ;

  // Check if the area already exist in areas
  auto i = areas.find(area_name) ;
  if (i != areas.end())
    {
      // Just return if area points to the already stored Area
      if (i->second == area)
        return ;
      // Otherwise throw an exception
      throw element_already_exists(
        "an Area named \""+ area_name +"\" is already stored") ;
    }

  // Store the area
  areas[area_name] = area ;
}



/* *** Operators *** */


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

  name = source.name ;
  areas = source.areas ;
  waypoints = source.waypoints ;

  return *this;
}


bool Building::operator==(const Building &source) const
{
  if (this == &source)
    return true ;

  return
    name == source.name &&
    areas == source.areas &&
    waypoints == source.waypoints ;
}



ostream& operator<<(ostream &os, const Building &b)
{
  os
      << b.name << " ("
      << b.areas.size() << " areas, "
      << b.waypoints.size() << " waypoints)" ;

  return os ;
}
