#include "ff/IBody.h"
#include "ff/Make.h"
#include "test/3rdparty/catch.hpp"
#include "test/util/RunMultiQ.h"

//! Compare form factor for particle shapes A and B, where A is given special
//! parameter values so that it coincides with the more symmetric B.

void run_test(const ff::IBody* p0, const ff::IBody* p1, const R3& d, double eps, double qmag1,
              double qmag2)
{
    int failures = formfactorTest::run_test_for_many_q(
        [&](C3 q) -> complex_t { return exp_I(d.dot(q)) * p0->formfactor(q); },
        [&](C3 q) -> complex_t { return p1->formfactor(q); }, qmag1, qmag2, eps);
    CHECK(failures == 0);
}

const double eps_polyh = 3e-13;

R3 d{0.2, -0.7, 11.3};

TEST_CASE("FormfactorTranslate.Cube", "")
{
    const double L = .5;
    const auto* p0 = ff::make::Box(L, L, L);
    auto* p1 = ff::make::Box(L, L, L);
    p1->move(d);
    run_test(p0, p1, d, eps_polyh, 1e-99, 5e2);
}

TEST_CASE("FormfactorTranslate.Pyramid3", "")
{
    const double L = 1.5, H = .24, alpha = .6;
    const auto* p0 = ff::make::Pyramid3(L, H, alpha);
    auto* p1 = ff::make::Pyramid3(L, H, alpha);
    p1->move(d);
    run_test(p0, p1, d, eps_polyh, 1e-99, 50);
}

TEST_CASE("FormfactorTranslate.Prism6", "")
{
    const double L = .8, H = 1.13;
    const auto* p0 = ff::make::Prism6(L, H);
    auto* p1 = ff::make::Prism6(L, H);
    p1->move(d);
    run_test(p0, p1, d, eps_polyh, 1e-99, 100);
}
