#include <xtd/collections/generic/list>
#include <xtd/console>
#include <xtd/iobservable>
#include <xtd/iobserver>
#include <xtd/system_exception>
 
 
 
struct location {
public:
  location(double latitude, double longitude) : latitutde_(latitude), longitude_(longitude) {}
  
  double latitude() const noexcept {return latitutde_;}
  double longitude() const noexcept {return longitude_;}
  
private:
  double latitutde_ = .0;
  double longitude_ = .0;
};
 
public:
  location_unknown_exception() {}
};
 
class location_tracker : 
public iobservable<location> {
 
public:
  location_tracker() = default;
  
    if (std::find(observers_.begin(), observers_.end(), &observer) == observers_.end())
      observers_.push_back(&observer);
  }
  
    auto iterator = std::find(observers_.begin(), observers_.end(), &observer);
    if (iterator != observers_.end())
      observers_.erase(iterator);
  }
  
  void track_location(std::optional<location> loc) {
    for (auto observer : observers_) {
      if (!loc.has_value())
        observer->on_error(location_unknown_exception());
      else
        observer->on_next(loc.value());
    }
  }
  
  void end_transmission() {
    for (auto observer : observers_)
      observer->on_completed();
    observers_.clear();
  }
  
private:
};
 
class location_reporter : 
iobserver<location> {
 
public:
  location_reporter(string name) : name_(name) {}
  virtual ~location_reporter() {unsubscribe();}
  
  string name() const noexcept {return name_;}
  
    provider_ = &provider;
  }
  
  void on_completed() noexcept override {
    console::write_line("The location Tracker has completed transmitting data to {}.", name());
    unsubscribe();
  }
  
  void on_error(const std::exception& e) noexcept override {
    console::write_line("{}: The location cannot be determined.", name());
  }
  
  void on_next(const location& value) noexcept override {
    console::write_line("{}: The current location is {}, {}", name(), value.latitude(), value.longitude());
  }
  
  virtual void unsubscribe() {
    if (provider_ != nullptr) provider_->unsubscribe(*this);
    provider_ = nullptr;
  }
  
private:
  string name_;
};
 
auto main() -> int {
  
  auto provider = location_tracker {};
  auto reporter1 = location_reporter {"Fixed GPS"};
  auto reporter2 = location_reporter {"Mobile GPS"};
  reporter2.subscribe(provider);
  
  provider.track_location(location {47.6456, -122.1312});
  provider.track_location(location {47.6677, -122.1199});
  provider.track_location(std::nullopt);
  provider.end_transmission();
}
 
Represents a strongly typed list of objects that can be accessed by index. Provides methods to search...
Definition list.hpp:71
 
Provides a mechanism for receiving push-based notifications.
Definition iobservable.hpp:155
 
virtual void subscribe(iobserver< type_t > &observer) noexcept=0
Notifies the provider that an observer is to receive notifications.
 
virtual void unsubscribe(iobserver< type_t > &observer) noexcept=0
Notifies the provider that an observer no longer wants to receive notifications.
 
Provides a mechanism for receiving push-based notifications.
Definition iobserver.hpp:154
 
The exception that is thrown when a method call is invalid for the object's current state.
Definition system_exception.hpp:18
 
The xtd::collections::generic namespace contains interfaces and classes that define generic collectio...
Definition comparer.hpp:15
 
The xtd namespace contains all fundamental classes to access Hardware, Os, System,...
Definition xtd_about_box.hpp:10