// 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() {
  // 2x2 matrix (column-major order)
  {
    Matrix<Scalar, 2, 2> m;
    m << Scalar(1), Scalar(2), Scalar(3), Scalar(4);
    auto [m00, m10, m01, m11] = m;
    // Column-major: (0,0), (1,0), (0,1), (1,1)
    VERIFY_IS_EQUAL(m00, Scalar(1));
    VERIFY_IS_EQUAL(m10, Scalar(3));
    VERIFY_IS_EQUAL(m01, Scalar(2));
    VERIFY_IS_EQUAL(m11, Scalar(4));
  }
}

template <typename Scalar>
void check_storage_order_semantics() {
  // Row vectors are forced to RowMajor by Eigen (a 1xN can't meaningfully be
  // column-major). Ensure decomposition still matches the single-row layout.
  {
    Matrix<Scalar, 1, 3> rv;
    rv << Scalar(1), Scalar(2), Scalar(3);
    auto [a, b, c] = rv;
    VERIFY_IS_EQUAL(a, Scalar(1));
    VERIFY_IS_EQUAL(b, Scalar(2));
    VERIFY_IS_EQUAL(c, Scalar(3));
  }
  // Nx1 column vectors are ColMajor regardless and decompose top-to-bottom.
  {
    Matrix<Scalar, 3, 1> cv;
    cv << Scalar(4), Scalar(5), Scalar(6);
    auto [a, b, c] = cv;
    VERIFY_IS_EQUAL(a, Scalar(4));
    VERIFY_IS_EQUAL(b, Scalar(5));
    VERIFY_IS_EQUAL(c, Scalar(6));
  }
  // 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));
}

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_6(check_storage_order_semantics<double>());
  CALL_SUBTEST_6(check_storage_order_semantics<int>());
}

#else

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

#endif
