#pragma once

#include <functional>
#include <string>
#include <map>
#include <vector>
#include <ctime>
#include <cmath>

class Cache;

enum Service {
	ocpl,
	ocde,
	ocus,
	ocro,
	ocuk,
	ocnl,
	none
};

const uint Earth_radius = 6378;
const uint Moon_dist = 384400;

typedef std::vector<Cache> Caches;
typedef std::vector<const Cache*> pCaches;
typedef std::multimap<std::time_t, const Cache*> Date_Caches;

const std::string flag_pl = "https://wiki.opencaching.eu/images/b/b7/Oc-pl.png";
const std::string flag_de = "https://wiki.opencaching.eu/images/c/c1/Oc-de.png";
const std::string flag_us = "https://wiki.opencaching.eu/images/f/fb/Oc-us.png";
const std::string flag_nl = "https://wiki.opencaching.eu/images/4/4b/Oc-nl.png";
const std::string flag_ro = "https://wiki.opencaching.eu/images/4/4f/Oc-ro.png";
const std::string flag_uk = "https://wiki.opencaching.eu/images/5/58/Oc-org-uk.png";

void htmlencode(std::string& data);

void show_histogram(const Caches& cc, std::string Cache::*ptr, const std::string& caption, bool html = 0, bool sort_by_val = 1);
void show_histogram(const pCaches& cc, std::string Cache::*ptr, const std::string& caption, bool html = 0, bool sort_by_val = 1);
void show_histogram(const std::map<std::string, int>& data, const std::string& caption, bool html = 0, bool sort_by_val = 1);
// void show_histogram(const pPowertrails& tt, const std::string& caption, bool html = 0, bool sort_by_val = 1);
void show_nested_histogram(const pCaches& fcc, std::string Cache::*ptr, std::string Cache::*ptr2, const std::string& caption, bool html = 0, bool sort_by_val = 1);

uint find_streak(const Date_Caches& cc, std::time_t& start);

uint get_num(char c, char* opt);

template <typename T>
void average_html(const Caches& cc, T Cache::*ptr, const std::string& caption);
template <typename T>
float average(const Caches& cc, T Cache::*ptr);

template <typename T>
void sum_html(const Caches& cc, T Cache::*ptr, const std::string& caption);
template <typename T>
T sum(const Caches& cc, T Cache::*ptr);

int count_caches(const Caches& cc, std::string& codes, std::function<bool(const Cache& c)> test);

void header_html();
void footer_html();

class Position {
public:
	float lat = 0;
	float lon = 0;

	Position() = default;
	Position(float y, float x) : lat(y), lon(x) {}
	explicit Position(const std::string& loc);
};

float cache_distance(const Cache& a, const Cache& b);

constexpr float degtorad(float x) {
	return x * M_PI / 180;
}
