#ifndef ROW_HPP
#define ROW_HPP

#include <iostream>
#include <cstdint>
#include <stdexcept>
#include "sort_algorithms.hpp"

template<typename T>
class row {
	private:
		T*p;
		uint32_t n;
	public:
		row(T* data, uint32_t size) : n(size) {
			p= new T[n];
			for (uint32_t i=0;i<n;i++) p[i] = data[i];

		}
		~row() {delete[] p;}
		row(const row& other) : n(other.n) {
			p = new T[n];
			for (uint32_t i=0;i<n;i++) p[i] = other.p[i];
		}
		row& operator=(const row& other) {
			if (this != &other) {
				delete[] p;
				n = other.n;
				p =new T[n];
				for (uint32_t i=0;i<n;i++) p[i]=other.p[i];
			}
			return *this;
		}
		T& operator[](uint32_t index) { return p[index];}
		const T& operator[](uint32_t index) const {return p[index];}
		T& at(uint32_t index){
			if (index >= n) throw std::out_of_range("Index out of bounds");
			return p[index];
		}
		const T& at(uint32_t index) const{
			if(index >= n) throw std::out_of_range("Index out of bounds");
			return p[index];
		}
		uint32_t size() const {return n;}

		friend std::ostream& operator<<(std::ostream& os, const row& r) {
			os << "[";
			for (uint32_t i=0;i<r.n;i++) os << r.p[i] << (i<r.n -1 ? "," : "");
			os << "]";
			return os;
		}
		friend std::istream& operator>>(std::istream& is,row& r){
			for (uint32_t i=0;i<r.n; i++) is >> r.p[i];
			return is;
		}
};
#endif
