#pragma once

#include <vector>
#include <hack/logger/logger.hpp>
#include "insertion_sort.hpp"

// Сортировка вставкой
// Эффективна на мелких массивах. Сложнгость O(N^2)
namespace alg_v2
{
  inline void merge(std::vector<int>& v, int left, int mid, int right) 
  {
    std::vector<int> l(v.begin() + left, v.begin() + mid + 1);
    std::vector<int> r(v.begin() + mid + 1, v.begin() + right + 1);

    int i = 0; // индекс для левой подсистемы
    int j = 0; // индекс для правой подсистемы
    int k = left; // индекс для A[p:r+1]

    // Объединение двух отсортированных подсистем
    while (i < l.size() && j < r.size()) 
    {
        if (l[i] <= r[j]) {
            v[k] = l[i];
            i++;
        } else {
            v[k] = r[j];
            j++;
        }
        k++;
    }

    // Копирование оставшихся элементов левой подсистемы (если есть)
    while (i < l.size()) 
    {
        v[k] = l[i];
        i++;
        k++;
    }

    // Копирование оставшихся элементов правой подсистемы (если есть)
    while (j < r.size()) {
        v[k] = r[j];
        j++;
        k++;
    }
  }

  inline void merge_sort_helper(std::vector<int>& v, int left, int right) 
  {
    if (left < right) 
    {
      int mid = (left + right) / 2;

      merge_sort_helper(v, left, mid);
      merge_sort_helper(v, mid + 1, right);

      merge(v, left, mid, right);
    }
  }

  inline void merge_sort(std::vector<int>& v)
  {
    merge_sort_helper(v, 0, v.size() - 1);
  }
}

