#pragma once
/*
 * (C) 2022 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 * All Rights Reserved
 *
 * Author: Eric Wild <ewild@sysmocom.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <string>
#include <tuple>

#include "Logger.h"

extern "C" {
#include <osmocom/gsm/gsm_utils.h>
}

template <typename powermapt, typename devmapt>
class band_manager {
	using powerkeyt = typename powermapt::key_type;
	using powermappedt = typename powermapt::mapped_type;
	using devkeyt = typename devmapt::key_type;
	const devkeyt &m_dev_type;
	const powermapt &m_power_map;
	const devmapt &m_dev_map;
	powerkeyt m_fallback;
	enum gsm_band m_band;
	powermappedt m_band_desc;
	bool band_ass_curr_sess{}; /* true if  "band" was set after last POWEROFF */

	// looks up either first tuple element (->enum) or straight enum
	template <typename T, typename std::enable_if<std::is_enum<T>::value>::type *dummy = nullptr>
	auto key_helper(T &t) -> T
	{
		return t;
	}

	template <typename T>
	auto key_helper(T t) -> typename std::tuple_element<0, T>::type
	{
		return std::get<0>(t);
	}

	void assign_band_desc(enum gsm_band req_band)
	{
		auto key = key_helper(m_dev_type);
		auto fallback_key = key_helper(m_fallback);
		auto it = m_power_map.find({ key, req_band });
		if (it == m_power_map.end()) {
			auto desc = m_dev_map.at(m_dev_type);
			LOGC(DDEV, ERROR) << "No Tx Power measurements exist for device " << desc.desc_str
					  << " on band " << gsm_band_name(req_band) << ", using fallback..";
			it = m_power_map.find({ fallback_key, req_band });
		}
		OSMO_ASSERT(it != m_power_map.end());
		m_band_desc = it->second;
	}

	bool set_band(enum gsm_band req_band)
	{
		if (band_ass_curr_sess && req_band != m_band) {
			LOGC(DDEV, ALERT) << "Requesting band " << gsm_band_name(req_band)
					  << " different from previous band " << gsm_band_name(m_band);
			return false;
		}

		if (req_band != m_band) {
			m_band = req_band;
			assign_band_desc(m_band);
		}
		band_ass_curr_sess = true;
		return true;
	}

    public:
	band_manager(const devkeyt &dev_type, const powermapt &power_map, const devmapt &dev_map, powerkeyt fallback)
		: m_dev_type(dev_type), m_power_map(power_map), m_dev_map(dev_map), m_fallback(fallback),
		  m_band((enum gsm_band)0)
	{
	}
	band_manager(const powermapt &power_map, const devmapt &dev_map)
		: m_dev_type(dev_map.begin()->first), m_power_map(power_map), m_dev_map(dev_map),
		  m_fallback(m_power_map.begin()->first), m_band((enum gsm_band)0)
	{
	}
	void band_reset()
	{
		band_ass_curr_sess = false;
	}

	void get_dev_band_desc(powermappedt &desc)
	{
		if (m_band == 0) {
			LOGC(DDEV, ERROR)
				<< "Power parameters requested before Tx Frequency was set! Providing band 900 by default...";
			assign_band_desc(GSM_BAND_900);
		}
		desc = m_band_desc;
	}

	bool update_band_from_freq(double wFreq, int chan, bool is_tx)
	{
		enum gsm_band req_band;
		auto dirstr = is_tx ? "Tx" : "Rx";
		auto req_arfcn = gsm_freq102arfcn(wFreq / 1000 / 100, !is_tx);
		if (req_arfcn == 0xffff) {
			LOGCHAN(chan, DDEV, ALERT)
				<< "Unknown ARFCN for " << dirstr << " Frequency " << wFreq / 1000 << " kHz";
			return false;
		}
		if (gsm_arfcn2band_rc(req_arfcn, &req_band) < 0) {
			LOGCHAN(chan, DDEV, ALERT) << "Unknown GSM band for " << dirstr << " Frequency " << wFreq
						   << " Hz (ARFCN " << req_arfcn << " )";
			return false;
		}

		return set_band(req_band);
	}
};