//
// Created by dominik on 12/14/24.
//

#include "nsiteconejump.h"
#include "coordinates.h"

#include <cmath>
#include <iostream>
#include <ostream>
#include <vector>

namespace motions {
    NSiteJumpOnCone::NSiteJumpOnCone(const double delta, const double eta, const int num_sites, const double chi, std::mt19937_64 &rng) :
    BaseMotion("NSiteJumpOnCone", delta, eta, rng),
    m_num_sites(num_sites),
    m_chi(chi*M_PI/180.) {}

    NSiteJumpOnCone::NSiteJumpOnCone(std::mt19937_64 &rng) : BaseMotion("NSiteJumpOnCone", rng) { }

    void NSiteJumpOnCone::initialize() {
        m_sites = std::vector<double>(m_num_sites);
        m_chooser = std::uniform_int_distribution<>{1, m_num_sites - 1};

        m_axis = draw_position();

        const double alpha = m_uni_dist(m_rng) * 2 * M_PI;
        const double steps = 2*M_PI / m_num_sites;
        for (int i = 0; i < m_num_sites; i++) {
            m_sites[i] = omega_q(rotate(m_axis, m_chi, i * steps + alpha));
        }
    }

    double NSiteJumpOnCone::jump() {
        m_cone_idx += m_chooser(m_rng);
        m_cone_idx %= m_num_sites;

        return m_sites[m_cone_idx];
    }

    void NSiteJumpOnCone::setParameters(const std::unordered_map<std::string, double> &parameters) {
        BaseMotion::setParameters(parameters);
        m_num_sites = static_cast<int>(parameters.at("num_sites"));
        m_chi = parameters.at("chi") * M_PI/180.;
    }

    std::unordered_map<std::string, double> NSiteJumpOnCone::getParameters() const {
        auto parameter = BaseMotion::getParameters();
        parameter["num_sites"] = m_num_sites;
        parameter["chi"] = m_chi * 180. / M_PI;

        return parameter;
    }

    std::string NSiteJumpOnCone::toString() const {
        return std::to_string(m_num_sites) + "SiteJumpOnCone/angle=" + std::to_string(m_chi*180/M_PI);
    }

} // motions