/*
 * C++ test to validate all FrVect constructors
 * This tests all FrVect constructor variants to ensure proper validation
 */

#include <iostream>
#include <memory>
#include <exception>
#include <vector>
#include <cstring>

// Include FrameCPP headers
#include "framecpp/Universal/FrVect.hh"
#include "framecpp/Universal/Dimension.hh"

using namespace FrameCPP::Universal;
using FrameCPP::BYTE_ORDER_HOST;

int main() {
    std::cout << "=== FrVect All Constructors Test ===" << std::endl;
    
    try {
        // Setup: Create test data
        std::cout << "Setup: Creating test data..." << std::endl;
        auto dim = std::make_shared<DimensionImpl::Data>(5, 1.0, "s", 0.0);
        std::vector<double> test_data = {1.0, 2.0, 3.0, 4.0, 5.0};
        std::cout << "✓ Test data created successfully" << std::endl;
        
        //=============================================================
        // Constructor 1: Default constructor
        //=============================================================
        std::cout << "\n--- Constructor 1: Default constructor ---" << std::endl;
        try {
            FrVect frvect_default;
            std::cout << "✓ Default constructor works" << std::endl;
        } catch (const std::exception& e) {
            std::cout << "✗ Default constructor failed: " << e.what() << std::endl;
            return 1;
        }
        
        //=============================================================
        // Constructor 2: Copy constructor
        //=============================================================
        std::cout << "\n--- Constructor 2: Copy constructor ---" << std::endl;
        try {
            FrVect frvect_original("original", FrVect::FR_VECT_8R, 1, dim.get(), "Hz");
            FrVect frvect_copy(frvect_original);
            std::cout << "✓ Copy constructor works" << std::endl;
        } catch (const std::exception& e) {
            std::cout << "✗ Copy constructor failed: " << e.what() << std::endl;
            return 1;
        }
        
        //=============================================================
        // Constructor 3: Main constructor with byte order and data
        // FrVect(name, type, nDim, dims, byte_order, data, unitY)
        //=============================================================
        std::cout << "\n--- Constructor 3: Main constructor ---" << std::endl;
        
        // Test 3A: Valid parameters
        try {
            FrVect frvect_main("test_main", FrVect::FR_VECT_8R, 1, dim.get(), BYTE_ORDER_HOST, test_data.data(), "Hz");
            std::cout << "✓ Main constructor with valid parameters works" << std::endl;
        } catch (const std::exception& e) {
            std::cout << "✗ Main constructor with valid parameters failed: " << e.what() << std::endl;
            return 1;
        }
        
        // Test 3B: Invalid nDim=0
        try {
            FrVect frvect_invalid("test_invalid", FrVect::FR_VECT_8R, 0, nullptr, BYTE_ORDER_HOST, nullptr, "Hz");
            std::cout << "✗ BUG: Main constructor should throw exception with nDim=0" << std::endl;
            return 1;
        } catch (const std::exception& e) {
            std::cout << "✓ Main constructor correctly threw exception with nDim=0: " << e.what() << std::endl;
        }
        
        // Test 3C: Invalid dims=nullptr with nDim>0
        try {
            FrVect frvect_invalid("test_invalid", FrVect::FR_VECT_8R, 1, nullptr, BYTE_ORDER_HOST, nullptr, "Hz");
            std::cout << "✗ BUG: Main constructor should throw exception with nullptr dims" << std::endl;
            return 1;
        } catch (const std::exception& e) {
            std::cout << "✓ Main constructor correctly threw exception with nullptr dims: " << e.what() << std::endl;
        }
        
        //=============================================================
        // Constructor 4: Compression constructor
        // FrVect(name, compress, type, nDim, dims, nData, nBytes, data, unitY)
        //=============================================================
        std::cout << "\n--- Constructor 4: Compression constructor ---" << std::endl;
        
        // Test 4A: Valid parameters
        try {
            boost::shared_array<unsigned char> data_array(new unsigned char[test_data.size() * sizeof(double)]);
            std::memcpy(data_array.get(), test_data.data(), test_data.size() * sizeof(double));
            
            FrVect frvect_compress("test_compress", FrVect::RAW, FrVect::FR_VECT_8R, 1, dim.get(), 
                                 test_data.size(), test_data.size() * sizeof(double), data_array, "Hz");
            std::cout << "✓ Compression constructor with valid parameters works" << std::endl;
        } catch (const std::exception& e) {
            std::cout << "✗ Compression constructor failed: " << e.what() << std::endl;
            return 1;
        }
        
        // Test 4B: Invalid nDim=0
        try {
            boost::shared_array<unsigned char> data_array(new unsigned char[8]);
            FrVect frvect_invalid("test_invalid", FrVect::RAW, FrVect::FR_VECT_8R, 0, nullptr, 1, 8, data_array, "Hz");
            std::cout << "✗ BUG: Compression constructor should throw exception with nDim=0" << std::endl;
            return 1;
        } catch (const std::exception& e) {
            std::cout << "✓ Compression constructor correctly threw exception with nDim=0: " << e.what() << std::endl;
        }
        
        //=============================================================
        // Constructor 5: Simplified string constructor  
        // FrVect(name, type, nDim, dims, unitY)
        //=============================================================
        std::cout << "\n--- Constructor 5: Simplified string constructor ---" << std::endl;
        
        // Test 5A: Valid parameters
        try {
            FrVect frvect_simple("test_simple", FrVect::FR_VECT_8R, 1, dim.get(), "Hz");
            std::cout << "✓ Simplified string constructor works" << std::endl;
        } catch (const std::exception& e) {
            std::cout << "✗ Simplified string constructor failed: " << e.what() << std::endl;
            return 1;
        }
        
        // Test 5B: Invalid nDim=0
        try {
            FrVect frvect_invalid("test_invalid", FrVect::FR_VECT_8R, 0, nullptr, "Hz");
            std::cout << "✗ BUG: Simplified constructor should throw exception with nDim=0" << std::endl;
            return 1;
        } catch (const std::exception& e) {
            std::cout << "✓ Simplified constructor correctly threw exception with nDim=0: " << e.what() << std::endl;
        }
        
        //=============================================================
        // Constructor 6 & 7: Template constructors (const T* and T*)
        // These are excluded from SWIG but we should test them in C++
        //=============================================================
        std::cout << "\n--- Constructor 6 & 7: Template constructors ---" << std::endl;
        
        // Test 6A: Template constructor with const double*
        try {
            FrVect frvect_template("test_template", 1, dim.get(), static_cast<const double*>(test_data.data()), "Hz");
            std::cout << "✓ Template constructor with const T* works" << std::endl;
        } catch (const std::exception& e) {
            std::cout << "✗ Template constructor with const T* failed: " << e.what() << std::endl;
            return 1;
        }
        
        // Test 6B: Template constructor with double*
        try {
            FrVect frvect_template2("test_template2", 1, dim.get(), test_data.data(), "Hz");
            std::cout << "✓ Template constructor with T* works" << std::endl;
        } catch (const std::exception& e) {
            std::cout << "✗ Template constructor with T* failed: " << e.what() << std::endl;
            return 1;
        }
        
        // Test 6C: Template constructor invalid nDim=0
        try {
            FrVect frvect_invalid("test_invalid", 0, nullptr, test_data.data(), "Hz");
            std::cout << "✗ BUG: Template constructor should throw exception with nDim=0" << std::endl;
            return 1;
        } catch (const std::exception& e) {
            std::cout << "✓ Template constructor correctly threw exception with nDim=0: " << e.what() << std::endl;
        }
        
        //=============================================================
        // Test boost::shared_ptr wrapping (SWIG compatibility)
        //=============================================================
        std::cout << "\n--- Boost shared_ptr compatibility test ---" << std::endl;
        try {
            boost::shared_ptr<FrVect> frvect_shared(new FrVect("test_shared", FrVect::FR_VECT_8R, 1, dim.get(), "Hz"));
            std::cout << "✓ boost::shared_ptr wrapping works" << std::endl;
        } catch (const std::exception& e) {
            std::cout << "✗ boost::shared_ptr wrapping failed: " << e.what() << std::endl;
            return 1;
        }
        
        std::cout << "\n=== All FrVect Constructor Tests Passed! ===" << std::endl;
        std::cout << "✓ All 7 constructor variants work correctly" << std::endl;
        std::cout << "✓ Input validation prevents segfaults and throws proper exceptions" << std::endl;
        std::cout << "✓ boost::shared_ptr compatibility confirmed" << std::endl;
        std::cout << "✓ SWIG Python bindings should now work correctly!" << std::endl;
        
    } catch (const std::exception& e) {
        std::cout << "✗ Unexpected exception: " << e.what() << std::endl;
        return 1;
    } catch (...) {
        std::cout << "✗ Unknown exception occurred" << std::endl;
        return 1;
    }
    
    return 0;
}