#include "user.h"
#include "ocdb.h"
#include "okapi.h"
// #include "gpx.h"
#include "debug.h"

void User::get_caches() {
	if (use_oc) {
		if (!ocpl_user_uuid.empty() || !ocpl_user.empty()) {
			Okapi OCpl(ocpl);
			uint uid;
			if (!ocpl_user.empty()) ocpl_user_uuid = OCpl.get_uuid(ocpl_user, &uid);
			Caches tmp = OCpl.get_user_caches(ocpl_user_uuid, 0);

			traildb.read_from_json("powertrails.json");
			tc.read_from_json("caches_in_power.json");

			std::unordered_map<int, Powertrail*> tt_map; // Needed to deduplicate trails

			for (auto& c : tmp) {
				if (tc.data.count(c.code) > 0) {
					c.trail = tc.data[c.code];
					traildb.data[c.trail].found++;
					if (c.status == ok)
						traildb.data[c.trail].active_caches_not_found--;
					tt_map[c.trail] = &(traildb.data[c.trail]);
				}
			}
			for (const auto& i : tt_map) {
				i.second->completed_perc = (100 * i.second->found / i.second->caches.size());
				if (i.second->found >= i.second->treshold)
					i.second->completed = 1;
				else
					i.second->needed = i.second->treshold - i.second->found;
				tt.push_back(i.second);
			}
			std::sort(tt.begin(), tt.end(), [&](const auto& a, const auto& b) { return a->completed_perc > b->completed_perc; });

			OCpl.get_ftf(uid, tmp);
			caches_hidden = OCpl.get_user_hidden_caches_no(ocpl_user_uuid);

			std::copy(tmp.begin(), tmp.end(), std::back_inserter(cc));
			ocpl_user_profile = OCpl.get_profile_url(ocpl_user_uuid);
		}
		if (!ocde_user_uuid.empty() || !ocde_user.empty()) {
			Okapi OCde(ocde);
			if (!ocde_user.empty()) ocde_user_uuid = OCde.get_uuid(ocde_user);
			Caches tmp = OCde.get_user_caches(ocde_user_uuid, 0);
			std::copy(tmp.begin(), tmp.end(), std::back_inserter(cc));
			ocde_user_profile = OCde.get_profile_url(ocde_user_uuid);
		}
		if (!ocus_user_uuid.empty() || !ocus_user.empty()) {
			Okapi OCus(ocus);
			if (!ocus_user.empty()) ocus_user_uuid = OCus.get_uuid(ocus_user);
			Caches tmp = OCus.get_user_caches(ocus_user_uuid, 0);
			std::copy(tmp.begin(), tmp.end(), std::back_inserter(cc));
			ocus_user_profile = OCus.get_profile_url(ocus_user_uuid);
		}
		if (!ocnl_user_uuid.empty() || !ocnl_user.empty()) {
			Okapi OCnl(ocnl);
			if (!ocnl_user.empty()) ocnl_user_uuid = OCnl.get_uuid(ocnl_user);
			Caches tmp = OCnl.get_user_caches(ocnl_user_uuid, 0);
			std::copy(tmp.begin(), tmp.end(), std::back_inserter(cc));
			ocnl_user_profile = OCnl.get_profile_url(ocnl_user_uuid);
		}
		if (!ocro_user_uuid.empty() || !ocro_user.empty()) {
			Okapi OCro(ocro);
			if (!ocro_user.empty()) ocro_user_uuid = OCro.get_uuid(ocro_user);
			Caches tmp = OCro.get_user_caches(ocro_user_uuid, 0);
			std::copy(tmp.begin(), tmp.end(), std::back_inserter(cc));
			ocro_user_profile = OCro.get_profile_url(ocro_user_uuid);
		}
		if (!ocuk_user_uuid.empty() || !ocuk_user.empty()) {
			Okapi OCuk(ocuk);
			if (!ocuk_user.empty()) ocuk_user_uuid = OCuk.get_uuid(ocuk_user);
			Caches tmp = OCuk.get_user_caches(ocuk_user_uuid, 0);
			std::copy(tmp.begin(), tmp.end(), std::back_inserter(cc));
			ocuk_user_profile = OCuk.get_profile_url(ocuk_user_uuid);
		}
	}

	// if (!gpx_file.empty()) {
	// 	GPX gpxfile(gpx_file);
	// 	Caches tmp = gpxfile.get_user_caches();
	// 	std::copy(tmp.begin(), tmp.end(), std::back_inserter(cc));
	// }

	if (use_ocdb) {
		if (!ocpl_user_uuid.empty() || !ocpl_user.empty()) {
			OCdb db(ocpl);
			if (!ocpl_user.empty()) {
				Okapi OCpl(ocpl);
				ocpl_user_uuid = OCpl.get_uuid(ocpl_user);
				ocpl_user_profile = OCpl.get_profile_url(ocpl_user_uuid);
			}
			if (get_not_found) {
				Caches tmp = db.get_user_caches_not_found(ocpl_user_uuid);
				Okapi OCpl(ocpl);
				OCpl.update_caches(tmp);
				std::copy(tmp.begin(), tmp.end(), std::back_inserter(cc));
				region_count = db.get_region_stats();
			} else if (get_owned) {
				Caches tmp = db.get_user_caches_owned(ocpl_user_uuid);
				Okapi OCpl(ocpl);
				OCpl.update_caches(tmp);
				std::copy(tmp.begin(), tmp.end(), std::back_inserter(cc));
			} else {
				Caches tmp = db.get_user_caches(ocpl_user_uuid, 0);
				std::copy(tmp.begin(), tmp.end(), std::back_inserter(cc));
			}
		}
		if (!ocde_user_uuid.empty() || !ocde_user.empty()) {
			OCdb db(ocde);
			if (!ocde_user.empty()) {
				Okapi OCde(ocde);
				ocde_user_uuid = OCde.get_uuid(ocde_user);
				ocde_user_profile = OCde.get_profile_url(ocde_user_uuid);
			}
			if (get_not_found) {
				Caches tmp = db.get_user_caches_not_found(ocde_user_uuid);
				Okapi OCde(ocde);
				OCde.update_caches(tmp);
				std::copy(tmp.begin(), tmp.end(), std::back_inserter(cc));
				// region_count = db.get_region_stats();
			} else if (get_owned) {
				Caches tmp = db.get_user_caches_owned(ocde_user_uuid);
				Okapi OCde(ocde);
				OCde.update_caches(tmp);
				std::copy(tmp.begin(), tmp.end(), std::back_inserter(cc));
			} else {
				Caches tmp = db.get_user_caches(ocde_user_uuid, 0);
				std::copy(tmp.begin(), tmp.end(), std::back_inserter(cc));
			}
		}
	}

	// TODO: some cache deduplication is needed

	Debug(2) << "Caches read: " << cc.size() << '\n';
	caches_count = cc.size();
}

void User::prepare_lists_of_caches() {
	// Prepare a set of regions
	Country poland({ "dolnoslaskie",
					 "gornoslaskie",
					 "kujawsko-pomorskie",
					 "lodzkie",
					 "lubelskie",
					 "lubuskie",
					 "malopolskie",
					 "mazowieckie",
					 "opolskie",
					 "podkarpackie",
					 "podlaskie",
					 "pomorskie",
					 "swietokrzyskie",
					 "warminsko-mazurskie",
					 "wielkopolskie",
					 "zachodniopomorskie" });

	if (!get_not_found) {
		for (auto i = cc.begin(); i != cc.end();) {
			if (time_filter && (i->date_t > end_time || i->date_t < start_time)) {
				i = cc.erase(i);
				continue;
			}

			poland.locate(*i);

			dates[i->date]++;
			sorted_caches.insert({ i->date_t, &*i });
			if ((i->type != "Moving" && i->type != "Own") || get_owned) {
				sorted_fcaches.insert({ i->date_t, &*i });
				fcc.push_back(&*i);
			}
			sorted_caches_by_hidden.insert({ i->date_hidden_t, &*i });
			caches_by_fav.push_back(&*i);
			caches_by_fav_perc.push_back(&*i);
			caches_by_finds.push_back(&*i);
			// caches_by_rating.push_back(&*i);
			if (i->ftf)
				caches_ftf.push_back(&*i);
			i++;
		}
		std::sort(caches_by_fav.begin(), caches_by_fav.end(), [&](const Cache* a, const Cache* b) { return a->fav > b->fav; });
		std::sort(caches_by_fav_perc.begin(), caches_by_fav_perc.end(), [&](const Cache* a, const Cache* b) { return 1.0 * a->fav / a->founds > 1.0 * b->fav / b->founds; });
		std::sort(caches_by_finds.begin(), caches_by_finds.end(), [&](const Cache* a, const Cache* b) { return a->founds > b->founds; });
		// std::sort(caches_by_rating.begin(), caches_by_rating.end(), [&](const Cache* a, const Cache* b) { return a->rating > b->rating; });
		std::sort(caches_ftf.begin(), caches_ftf.end(), [&](const Cache* a, const Cache* b) { return a->date_t < b->date_t; });
	} else {
		for (auto& i : cc) {
			if (i.type != "Moving" && i.type != "Own" && (!exclude_quiz || i.type != "Quiz")) {
				fcc.push_back(&i);
				poland.locate(i);
			}
		}
	}
}

void User::header() const {
	if (!ocpl_user.empty())
		std::cout << "<img alt=\"OCpl\" src=\"" << flag_pl << "\"> <a href=\"" << ocpl_user_profile << "\">" << ocpl_user << "</a><br>\n";
	if (!ocde_user.empty())
		std::cout << "<img alt=\"OCde\" src=\"" << flag_de << "\"> <a href=\"" << ocde_user_profile << "\">" << ocde_user << "</a><br>\n";
	if (!ocus_user.empty())
		std::cout << "<img alt=\"OCna\" src=\"" << flag_us << "\"> <a href=\"" << ocus_user_profile << "\">" << ocus_user << "</a><br>\n";
	if (!ocnl_user.empty())
		std::cout << "<img alt=\"OCnl\" src=\"" << flag_nl << "\"> <a href=\"" << ocnl_user_profile << "\">" << ocnl_user << "</a><br>\n";
	if (!ocro_user.empty())
		std::cout << "<img alt=\"OCro\" src=\"" << flag_ro << "\"> <a href=\"" << ocro_user_profile << "\">" << ocro_user << "</a><br>\n";
	if (!ocuk_user.empty())
		std::cout << "<img alt=\"OCuk\" src=\"" << flag_uk << "\"> <a href=\"" << ocuk_user_profile << "\">" << ocuk_user << "</a><br>\n";
}
