// SPDX-License-Identifier: LGPL-3.0-or-later
// Author: Kristian Lytje

#pragma once

#include <crystal/miller/ReducedMillers.h>
#include <math/Vector3.h>

namespace ausaxs::crystal {
    /**
     * @brief The FibonacciMillers class generates a set of Miller indices using the Fibonacci sphere algorithm.
     * 
     * First all independent bases smaller than setting::crystal::max_q are generated. 
     * Then the Fibonacci sphere is used to pick a subset of these bases, to force a more uniform distribution.
     * Finally, all Miller indices are generated by multiplying the bases with integers, out to the limit setting::crystal::h setting::crystal::k setting::crystal::l.
     */
    class FibonacciMillers : public ReducedMillers {
        public:
            FibonacciMillers(unsigned int h, unsigned int k, unsigned int l);
            ~FibonacciMillers() override = default;

            std::vector<Miller> generate() const override;

        private:
            static inline double phi = (1 + sqrt(5))/2;

            int estimate_n(double resolution) const;

            std::vector<Miller> pick_directions(std::vector<Miller>&& basis) const;
            std::vector<Miller> pick_directions(const std::vector<Miller>& basis) const;

            std::vector<Vector3<double>> generate_fibonacci_sphere(int n) const;
    };
}