#pragma once

#include <Indoor/grid/GridPoint.h>
#include <Indoor/data/Timestamp.h>
#include <Indoor/sensors/radio/VAPGrouper.h>

namespace Settings {

    const bool useKLB = false;

    const int numParticles = 5000;
    const int numBSParticles = 50;

	namespace IMU {
        const float turnSigma = 2.5;		// 3.5
        const float stepLength = 1.00;
        const float stepSigma = 0.15; //toni changed
	}

	const float smartphoneAboveGround = 1.3;

	const float offlineSensorSpeedup = 2;

	namespace Grid {
		constexpr int gridSize_cm = 20;
	}

    namespace Smoothing {
        const bool activated = true;
        const double stepLength = 0.7;
        const double stepSigma = 0.2;
        const double headingSigma = 25.0;
        const double zChange = 0.0; // mu change in height between two time steps
        const double zSigma = 0.1;
        const int lag = 5;

    }

    namespace KDE {
        const Point2 bandwidth(1,1);
		const float  gridSize = 0.2;
    }

	namespace KDE3D {
		const Point3 bandwidth(1, 1, 1);
		const Point3 gridSize(0.2, 0.2, 1); // in meter
	}

	//const GridPoint destination = GridPoint(70*100, 35*100, 0*100);		// use destination
	const GridPoint destination = GridPoint(0,0,0);							// do not use destination

	namespace SensorDebug {
		const Timestamp updateEvery = Timestamp::fromMS(200);
	}

    namespace WiFiModel {
        constexpr float sigma = 8.0;
		/** if the wifi-signal-strengths are stored on the grid-nodes, this needs a grid rebuild! */
        constexpr float TXP = -45;
        constexpr float EXP = 2.3;
        constexpr float WAF = -11.0;

        const bool optimize = false;
        const bool useRegionalOpt = false;

        // how to perform VAP grouping. see
        // - calibration in Controller.cpp
        // - eval in Filter.h
        // NOTE: maybe the UAH does not allow valid VAP grouping? delete the grid and rebuild without!
		const VAPGrouper vg_calib = VAPGrouper(VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, VAPGrouper::Aggregation::MAXIMUM, VAPGrouper::TimeAggregation::AVERAGE, 1);	// Frank: WAS MAXIMUM
		const VAPGrouper vg_eval  = VAPGrouper(VAPGrouper::Mode::LAST_MAC_DIGIT_TO_ZERO, VAPGrouper::Aggregation::MAXIMUM, VAPGrouper::TimeAggregation::AVERAGE, 1);	// Frank: WAS MAXIMUM
	}

    namespace BeaconModel {
        constexpr float sigma = 8.0;
        constexpr float TXP = -71;
        constexpr float EXP = 1.5;
        constexpr float WAF = -20.0; //-5 //20??
    }

	namespace MapView3D {
        const int maxColorPoints = 1000;
		constexpr int fps = 15;
		const Timestamp msPerFrame = Timestamp::fromMS(1000/fps);
	}

	namespace Filter {
		const Timestamp updateEvery = Timestamp::fromMS(500);
		constexpr bool useMainThread = false;						// perform filtering in the main thread
	}
    
	const std::string mapDir = "../map/";
	const std::string dataDir = "../measurements/data/";
	const std::string errorDir = "../measurements/error/";
    
    /** describes one dataset (map, training, parameter-estimation, ...) */

    const MACAddress NUC1("38:de:ad:6d:77:25");
    const MACAddress NUC2("38:de:ad:6d:60:ff");
    const MACAddress NUC3("1c:1b:b5:ef:a2:9a");
    const MACAddress NUC4("1c:1b:b5:ec:d1:82");

    struct NUCSettings
    {
        int ID = 0;
        Point3 position = { 0,0,0 };
        float ftm_offset = 0.0f;
        float rssi_pathloss = 0.0f;
        float kalman_measStdDev = 0.0f;
    };

    struct DataSetup {
        std::string map;
        std::vector<std::string> training;
        std::unordered_map<MACAddress, NUCSettings> NUCs;
        std::vector<int> gtPath;
    };

    /** all configured datasets */
    const struct Data {

        const DataSetup Path0 = {
            mapDir + "map0_ap_path0.xml",
            {
                dataDir + "Pixel2/Path0_0605.csv",
            },
            {
                { NUC1, {1, { 7.5, 18.7, 0.8}, 1.25, 3.375, 6.156} }, // NUC 1
                { NUC2, {2, { 8.6, 26.8, 0.8}, 2.00, 3.000, 5.650} }, // NUC 2
                { NUC3, {3, {21.6, 19.1, 0.8}, 1.75, 3.375, 6.107} }, // NUC 3
                { NUC4, {4, {20.8, 27.1, 0.8}, 2.75, 2.750, 3.985} }, // NUC 4
            },
            { 0, 1, 2, 3 }
        };
        const DataSetup Path1 = {
            mapDir + "map2_ap_path1.xml",
            {
                dataDir + "Pixel2/Path1_7208.csv",
            },
            {
                { NUC1, {1, { 8.1, 18.7, 0.8}, 0, 0, 0} }, // NUC 1
                { NUC2, {2, { 8.4, 27.3, 0.8}, 0, 0, 0} }, // NUC 2
                { NUC3, {3, {21.3, 19.3, 0.8}, 0, 0, 0} }, // NUC 3
                { NUC4, {4, {20.6, 26.8, 0.8}, 0, 0, 0} }, // NUC 4
            },
            { 1, 2, 6, 7, 6, 2, 1 }
        };
        
        const DataSetup CurrentPath = Path1;

    } data;

}

