/**
 * META-AWARE COMPONENT
 *
 * STRUCTURAL PATTERN: Divide and Conquer (Merge Sort)
 * ABSTRACTION LEVEL: High
 * COMPLEXITY: 6/10
 *
 * PURPOSE: Implements merge sort with explicit pattern awareness and self-documentation
 * WHY THIS PATTERN: Divide-and-conquer is a fundamental algorithmic pattern that demonstrates
 *                    clear recursive structure, making it ideal for meta-aware documentation
 *
 * QUALITY SELF-ASSESSMENT:
 * - Structural Clarity: 8/10 (clear recursive structure, well-commented)
 * - Meta-Awareness: 7/10 (pattern is explicit, trade-offs documented)
 * - Evolution Potential: 8/10 (multiple optimization paths identified)
 * - Pattern Generalizability: 9/10 (divide-and-conquer applies broadly)
 * - Self-Documentation Quality: 8/10 (comprehensive annotations)
 *
 * IMPROVEMENT SUGGESTIONS:
 * 1. Add complexity analysis annotations (O-notation) at each recursive level
 * 2. Implement adaptive strategy selection (switch to insertion sort for small arrays)
 * 3. Add performance metrics tracking to measure actual vs theoretical performance
 *
 * EVOLUTION PATH:
 * - Next step: Add runtime complexity tracking to validate O(n log n) behavior
 * - Long-term: Generalize to a meta-sort framework that auto-selects optimal algorithm
 */

// === IMPLEMENTATION ===

class MetaAwareMergeSort {
  constructor() {
    // Meta-tracking: count operations to validate complexity
    this.comparisons = 0;
    this.merges = 0;
  }

  /**
   * Main sort entry point
   * Pattern: Divide and Conquer
   * Complexity: O(n log n) time, O(n) space
   */
  sort(array) {
    this.comparisons = 0;
    this.merges = 0;

    if (array.length <= 1) {
      return array;
    }

    const result = this._mergeSort(array);

    // Meta-awareness: report on actual operations
    console.log(`[META] Sorted ${array.length} items with ${this.comparisons} comparisons, ${this.merges} merges`);
    console.log(`[META] Theoretical minimum: ~${Math.ceil(array.length * Math.log2(array.length))} operations`);

    return result;
  }

  /**
   * Recursive divide phase
   * Pattern Application: Split problem into two halves
   */
  _mergeSort(array) {
    // Base case: array of 1 element is already sorted
    if (array.length <= 1) {
      return array;
    }

    // Divide: split array in half
    const mid = Math.floor(array.length / 2);
    const left = array.slice(0, mid);
    const right = array.slice(mid);

    // Conquer: recursively sort both halves
    const sortedLeft = this._mergeSort(left);
    const sortedRight = this._mergeSort(right);

    // Combine: merge the sorted halves
    return this._merge(sortedLeft, sortedRight);
  }

  /**
   * Merge phase
   * Pattern Application: Combine two sorted arrays into one
   */
  _merge(left, right) {
    this.merges++;
    const result = [];
    let leftIndex = 0;
    let rightIndex = 0;

    // Compare elements from both arrays and build sorted result
    while (leftIndex < left.length && rightIndex < right.length) {
      this.comparisons++;

      if (left[leftIndex] <= right[rightIndex]) {
        result.push(left[leftIndex]);
        leftIndex++;
      } else {
        result.push(right[rightIndex]);
        rightIndex++;
      }
    }

    // Append remaining elements
    return result.concat(left.slice(leftIndex)).concat(right.slice(rightIndex));
  }

  /**
   * Self-assessment method
   * Pattern: Introspection
   */
  getMetrics() {
    return {
      comparisons: this.comparisons,
      merges: this.merges,
      pattern: 'Divide and Conquer',
      complexity: 'O(n log n)',
      spaceComplexity: 'O(n)'
    };
  }
}

// === STRUCTURAL REFLECTION ===
// Pattern Used: Divide and Conquer (recursive decomposition)
// Why: This pattern is optimal for sorting with guaranteed O(n log n) performance
//      and demonstrates clear recursive structure ideal for meta-documentation
// Trade-offs:
//   - Requires O(n) extra space (vs in-place sorts like quicksort variant)
//   - Not adaptive (doesn't benefit from pre-sorted data like insertion sort)
//   - Recursion overhead for very small arrays

// === META-ANALYSIS ===
// What worked well:
//   - Clear separation of divide/conquer/combine phases
//   - Self-tracking of operations validates theoretical complexity
//   - Pattern is highly transferable to other divide-conquer problems
// What could improve:
//   - Add adaptive threshold to switch to simpler algorithm for small arrays
//   - Implement iterative version to avoid recursion stack overhead
//   - Add visualization hooks to demonstrate recursive decomposition
// Generalizability:
//   - This divide-and-conquer pattern applies to: binary search, quicksort,
//     closest pair problems, fast Fourier transform, matrix multiplication

// === USAGE EXAMPLE ===
const sorter = new MetaAwareMergeSort();
const unsorted = [64, 34, 25, 12, 22, 11, 90];
const sorted = sorter.sort(unsorted);
console.log('Sorted:', sorted);
console.log('Metrics:', sorter.getMetrics());

module.exports = MetaAwareMergeSort;
