// SPDX-License-Identifier: Apache-2.0
// Copyright 2025 Median of Two Sorted Arrays Example
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "MedianFinder.h"
#include <iostream>
#include <vector>
#include <limits>

/**
 * Interactive demo function that allows users to input their own arrays
 */
void RunInteractiveDemo() {
    std::cout << "\n=== Interactive Median Finder Demo ===" << std::endl;
    std::cout << "Enter two sorted arrays to find their median." << std::endl;
    
    // Get first array
    std::cout << "\nEnter size of first array (0 for empty): ";
    int size1;
    std::cin >> size1;
    
    // Validate input
    if (std::cin.fail() || size1 < 0) {
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        std::cout << "Invalid input. Please enter a non-negative integer." << std::endl;
        return;
    }
    
    std::vector<int> nums1(size1);
    if (size1 > 0) {
        std::cout << "Enter " << size1 << " sorted elements for first array: ";
        for (int i = 0; i < size1; i++) {
            std::cin >> nums1[i];
            if (std::cin.fail()) {
                std::cin.clear();
                std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
                std::cout << "Invalid input. Please enter integers only." << std::endl;
                return;
            }
        }
    }
    
    // Get second array
    std::cout << "Enter size of second array (0 for empty): ";
    int size2;
    std::cin >> size2;
    
    if (std::cin.fail() || size2 < 0) {
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        std::cout << "Invalid input. Please enter a non-negative integer." << std::endl;
        return;
    }
    
    std::vector<int> nums2(size2);
    if (size2 > 0) {
        std::cout << "Enter " << size2 << " sorted elements for second array: ";
        for (int i = 0; i < size2; i++) {
            std::cin >> nums2[i];
            if (std::cin.fail()) {
                std::cin.clear();
                std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
                std::cout << "Invalid input. Please enter integers only." << std::endl;
                return;
            }
        }
    }
    
    // Validate that both arrays are empty
    if (size1 == 0 && size2 == 0) {
        std::cout << "Error: Both arrays cannot be empty." << std::endl;
        return;
    }
    
    try {
        // Show both approaches
        std::cout << "\n--- Results ---" << std::endl;
        
        double median_binary = MedianFinder::FindMedianSortedArrays(nums1, nums2);
        std::cout << "Binary Search Approach: " << median_binary << std::endl;
        
        double median_merge = MedianFinder::FindMedianMergeApproach(nums1, nums2);
        std::cout << "Merge Approach: " << median_merge << std::endl;
        
        std::cout << "\nComplexity Information:" << std::endl;
        std::cout << MedianFinder::GetComplexityInfo(true) << std::endl;
        
    } catch (const std::exception& e) {
        std::cout << "Error: " << e.what() << std::endl;
    }
}

/**
 * Displays program menu and handles user choice
 */
void DisplayMenu() {
    std::cout << "\n=== Median of Two Sorted Arrays - Menu ===" << std::endl;
    std::cout << "1. Run automated test suite" << std::endl;
    std::cout << "2. Run interactive demo" << std::endl;
    std::cout << "3. Run random stress tests" << std::endl;
    std::cout << "4. Show algorithm complexity information" << std::endl;
    std::cout << "5. Exit" << std::endl;
    std::cout << "Enter your choice (1-5): ";
}

/**
 * Main function with menu-driven interface
 */
int main() {
    std::cout << "Median of Two Sorted Arrays - C++ Implementation" << std::endl;
    std::cout << "=================================================" << std::endl;
    std::cout << "This program demonstrates two approaches to find the median of two sorted arrays:" << std::endl;
    std::cout << "1. Binary Search Approach - O(log(min(m,n))) time complexity" << std::endl;
    std::cout << "2. Merge Approach - O(m+n) time complexity" << std::endl;
    
    int choice;
    bool continue_program = true;
    
    while (continue_program) {
        DisplayMenu();
        std::cin >> choice;
        
        if (std::cin.fail()) {
            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            std::cout << "Invalid input. Please enter a number between 1 and 5." << std::endl;
            continue;
        }
        
        switch (choice) {
            case 1:
                MedianTester::RunTests();
                break;
                
            case 2:
                RunInteractiveDemo();
                break;
                
            case 3: {
                std::cout << "\nEnter number of random tests to run (default 100): ";
                int num_tests = 100;
                std::cin >> num_tests;
                if (std::cin.fail() || num_tests <= 0) {
                    std::cin.clear();
                    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
                    num_tests = 100;
                    std::cout << "Using default value: 100 tests" << std::endl;
                }
                MedianTester::RunRandomTests(num_tests);
                break;
            }
            
            case 4:
                std::cout << "\n=== Algorithm Complexity Information ===" << std::endl;
                std::cout << MedianFinder::GetComplexityInfo(true) << std::endl << std::endl;
                std::cout << MedianFinder::GetComplexityInfo(false) << std::endl;
                break;
                
            case 5:
                continue_program = false;
                std::cout << "Thank you for using the Median Finder program!" << std::endl;
                break;
                
            default:
                std::cout << "Invalid choice. Please enter a number between 1 and 5." << std::endl;
                break;
        }
        
        if (continue_program) {
            std::cout << "\nPress Enter to continue...";
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
            std::cin.get();
        }
    }
    
    return 0;
}