// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2026 Pavel Guzenfeld
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// SPDX-License-Identifier: MPL-2.0

#include "main.h"

#if EIGEN_MAX_CPP_VER >= 17 && EIGEN_COMP_CXXVER >= 17

template <typename Scalar>
void check_vector_bindings() {
  // Vector2
  {
    Matrix<Scalar, 2, 1> v;
    v << Scalar(1), Scalar(2);
    auto [x, y] = v;
    VERIFY_IS_EQUAL(x, Scalar(1));
    VERIFY_IS_EQUAL(y, Scalar(2));
  }

  // Vector3
  {
    Matrix<Scalar, 3, 1> v;
    v << Scalar(3), Scalar(4), Scalar(5);
    auto [x, y, z] = v;
    VERIFY_IS_EQUAL(x, Scalar(3));
    VERIFY_IS_EQUAL(y, Scalar(4));
    VERIFY_IS_EQUAL(z, Scalar(5));
  }

  // Vector4
  {
    Matrix<Scalar, 4, 1> v;
    v << Scalar(6), Scalar(7), Scalar(8), Scalar(9);
    auto [a, b, c, d] = v;
    VERIFY_IS_EQUAL(a, Scalar(6));
    VERIFY_IS_EQUAL(b, Scalar(7));
    VERIFY_IS_EQUAL(c, Scalar(8));
    VERIFY_IS_EQUAL(d, Scalar(9));
  }

  // 1x1 matrix (scalar-like)
  {
    Matrix<Scalar, 1, 1> s;
    s << Scalar(42);
    auto [val] = s;
    VERIFY_IS_EQUAL(val, Scalar(42));
  }

  // RowVector
  {
    Matrix<Scalar, 1, 3> rv;
    rv << Scalar(10), Scalar(20), Scalar(30);
    auto [a, b, c] = rv;
    VERIFY_IS_EQUAL(a, Scalar(10));
    VERIFY_IS_EQUAL(b, Scalar(20));
    VERIFY_IS_EQUAL(c, Scalar(30));
  }
}

template <typename Scalar>
void check_array_bindings() {
  // Array3
  {
    Array<Scalar, 3, 1> a;
    a << Scalar(100), Scalar(200), Scalar(300);
    auto [x, y, z] = a;
    VERIFY_IS_EQUAL(x, Scalar(100));
    VERIFY_IS_EQUAL(y, Scalar(200));
    VERIFY_IS_EQUAL(z, Scalar(300));
  }

  // Array2
  {
    Array<Scalar, 2, 1> a;
    a << Scalar(10), Scalar(20);
    auto [x, y] = a;
    VERIFY_IS_EQUAL(x, Scalar(10));
    VERIFY_IS_EQUAL(y, Scalar(20));
  }
}

template <typename Scalar>
void check_reference_bindings() {
  // Mutable reference binding
  {
    Matrix<Scalar, 3, 1> v;
    v << Scalar(1), Scalar(2), Scalar(3);
    auto& [x, y, z] = v;
    x = Scalar(10);
    y = Scalar(20);
    z = Scalar(30);
    VERIFY_IS_EQUAL(v(0), Scalar(10));
    VERIFY_IS_EQUAL(v(1), Scalar(20));
    VERIFY_IS_EQUAL(v(2), Scalar(30));
  }

  // Const reference binding
  {
    const Matrix<Scalar, 3, 1> v(Scalar(4), Scalar(5), Scalar(6));
    const auto& [x, y, z] = v;
    VERIFY_IS_EQUAL(x, Scalar(4));
    VERIFY_IS_EQUAL(y, Scalar(5));
    VERIFY_IS_EQUAL(z, Scalar(6));
  }

  // Array mutable reference binding
  {
    Array<Scalar, 2, 1> a;
    a << Scalar(7), Scalar(8);
    auto& [x, y] = a;
    x = Scalar(70);
    VERIFY_IS_EQUAL(a(0), Scalar(70));
    VERIFY_IS_EQUAL(a(1), Scalar(8));
  }
}

template <typename Scalar>
void check_matrix_bindings() {
  // 2D ColMajor matrix decomposes in column-major order: (0,0),(1,0),(0,1),(1,1).
  // 2D RowMajor is rejected via static_assert — see failtest/structured_bindings_rowmajor.cpp.
  {
    Matrix<Scalar, 2, 2, ColMajor> m;
    m << Scalar(1), Scalar(2), Scalar(3), Scalar(4);
    auto [m00, m10, m01, m11] = m;
    VERIFY_IS_EQUAL(m00, Scalar(1));
    VERIFY_IS_EQUAL(m10, Scalar(3));
    VERIFY_IS_EQUAL(m01, Scalar(2));
    VERIFY_IS_EQUAL(m11, Scalar(4));
  }
}

void check_tuple_size() {
  STATIC_CHECK((std::tuple_size<Vector2d>::value == 2));
  STATIC_CHECK((std::tuple_size<Vector3f>::value == 3));
  STATIC_CHECK((std::tuple_size<Vector4i>::value == 4));
  STATIC_CHECK((std::tuple_size<Matrix2d>::value == 4));
  STATIC_CHECK((std::tuple_size<Matrix3f>::value == 9));
  STATIC_CHECK((std::tuple_size<Array3i>::value == 3));
  STATIC_CHECK((std::tuple_size<Array<double, 2, 1>>::value == 2));
  STATIC_CHECK((std::tuple_size<Matrix<float, 1, 1>>::value == 1));
  STATIC_CHECK((std::tuple_size<RowVector3d>::value == 3));
}

void check_tuple_element() {
  STATIC_CHECK((std::is_same<std::tuple_element_t<0, Vector3d>, double>::value));
  STATIC_CHECK((std::is_same<std::tuple_element_t<1, Vector3f>, float>::value));
  STATIC_CHECK((std::is_same<std::tuple_element_t<2, Vector4i>, int>::value));
  STATIC_CHECK((std::is_same<std::tuple_element_t<0, Array3i>, int>::value));
}

// Emulates generic tuple-like detection as done by fmt's range formatter
// (issue #3103): probing tuple_size<T>::value in a SFINAE context must be a
// substitution failure for dynamic-size types, not a hard error.
template <typename T, typename = void>
struct is_tuple_like : std::false_type {};

template <typename T>
struct is_tuple_like<T, internal::void_t<decltype(std::tuple_size<T>::value)>> : std::true_type {};

template <typename T, typename = void>
struct has_tuple_element0 : std::false_type {};

template <typename T>
struct has_tuple_element0<T, internal::void_t<typename std::tuple_element<0, T>::type>> : std::true_type {};

void check_sfinae_friendly_detection() {
  STATIC_CHECK((is_tuple_like<Vector3d>::value));
  STATIC_CHECK((is_tuple_like<Matrix2f>::value));
  STATIC_CHECK((is_tuple_like<Array3i>::value));
  STATIC_CHECK((!is_tuple_like<VectorXd>::value));
  STATIC_CHECK((!is_tuple_like<MatrixXf>::value));
  STATIC_CHECK((!is_tuple_like<ArrayXd>::value));
  STATIC_CHECK((!is_tuple_like<Matrix<double, 3, Dynamic>>::value));
  STATIC_CHECK((!is_tuple_like<Matrix<double, Dynamic, 3>>::value));
  STATIC_CHECK((has_tuple_element0<Vector3d>::value));
  STATIC_CHECK((has_tuple_element0<Array3i>::value));
  STATIC_CHECK((!has_tuple_element0<VectorXd>::value));
  STATIC_CHECK((!has_tuple_element0<ArrayXXf>::value));
}

EIGEN_DECLARE_TEST(structured_bindings) {
  CALL_SUBTEST_1(check_vector_bindings<double>());
  CALL_SUBTEST_1(check_vector_bindings<float>());
  CALL_SUBTEST_1(check_vector_bindings<int>());
  CALL_SUBTEST_2(check_array_bindings<double>());
  CALL_SUBTEST_2(check_array_bindings<int>());
  CALL_SUBTEST_3(check_reference_bindings<double>());
  CALL_SUBTEST_3(check_reference_bindings<float>());
  CALL_SUBTEST_4(check_matrix_bindings<double>());
  CALL_SUBTEST_4(check_matrix_bindings<int>());
  CALL_SUBTEST_5(check_tuple_size());
  CALL_SUBTEST_5(check_tuple_element());
  CALL_SUBTEST_5(check_sfinae_friendly_detection());
}

#else

EIGEN_DECLARE_TEST(structured_bindings) {
  // Structured bindings require C++17.
  VERIFY(true);
}

#endif
