#pragma once

#include "cfg-value.h"

namespace scm
{
	class cfgVector
	{
	public:
		
		// set & add calls
		// -------------------------------------------------------------------------------------------- //
		void set(const cfgValue& value);
		void set(const cfgValue& value, const int size);

		void set(const int* x, const int size);
		void set(const float* x, const int size);
		void set(const double* x, const int size);
		void set(const long double* x, const int size);

		bool change(const int idx, const cfgValue& value);
		void append(const cfgValue& value);

		void set_name(const char* name);
		//		*: name == NULL - not changing vector name
		// -------------------------------------------------------------------------------------------- //
		
		// get calls
		// -------------------------------------------------------------------------------------------- //
		const cfgValue get(const int idx) const;
		
		bool get(const int idx, int* value) const;
		bool get(const int idx, float* value) const;
		bool get(const int idx, double* value) const;
		bool get(const int idx, long double* value) const;
		bool get(const int idx, char** c_str) const;
		bool get(const int idx, std::string& value) const;
		bool get(const int idx, bool* value) const;

		bool get_if_single(int* value) const;
		bool get_if_single(float* value) const;
		bool get_if_single(double* value) const;
		bool get_if_single(long double* value) const;
		bool get_if_single(char** c_str) const;
		bool get_if_single(std::string& value) const;
		bool get_if_single(bool* value) const;

		int get_size() const;
		const char* get_name() const;
		// -------------------------------------------------------------------------------------------- //

		// check calls
		// -------------------------------------------------------------------------------------------- //
		bool is_defined() const;
		//		*: size != 0 && all values defined
		bool is_empty() const;
		//		*: size == 0 
		bool is_name_empty() const;
		//		*: name = "\0";
		bool is_name_eq(const cfgVector& x) const;
		bool is_name_eq(const char* name) const;
		bool is_single() const;
		//		*: size == 1
		// -------------------------------------------------------------------------------------------- //

		// print
		// -------------------------------------------------------------------------------------------- //
		void print() const;
		void print_value() const;
		// -------------------------------------------------------------------------------------------- //

		// operators
		// -------------------------------------------------------------------------------------------- //
		cfgVector& operator+=(const cfgVector& x);
		cfgVector& operator-=(const cfgVector& x);
		cfgVector& operator*=(const cfgVector& x);
		cfgVector& operator/=(const cfgVector& x);
		cfgVector& operator%=(const cfgVector& x);
		cfgVector& operator^=(const cfgVector& x);

		const cfgVector operator+(const cfgVector& x) const;
		const cfgVector operator-(const cfgVector& x) const;
		const cfgVector operator*(const cfgVector& x) const;
		const cfgVector operator/(const cfgVector& x) const;
		const cfgVector operator%(const cfgVector& x) const;
		const cfgVector operator^(const cfgVector& x) const;

		const cfgVector operator==(const cfgVector& x) const;
		const cfgVector operator!=(const cfgVector& x) const;
		const cfgVector operator<(const cfgVector& x) const;
		const cfgVector operator>(const cfgVector& x) const;
		const cfgVector operator<=(const cfgVector& x) const;
		const cfgVector operator>=(const cfgVector& x) const;

		const cfgVector operator-() const;
		const cfgVector operator+() const;

		const cfgVector logical_and(const cfgVector& x) const;	// no short-circuit
		const cfgVector logical_or(const cfgVector& y) const;	// no short-circuit
		// -------------------------------------------------------------------------------------------- //

		// functions
		// -------------------------------------------------------------------------------------------- //
		static const cfgVector cfg_sin(const cfgVector& x);
		static const cfgVector cfg_cos(const cfgVector& x);
		static const cfgVector cfg_tan(const cfgVector& x);
		static const cfgVector cfg_log(const cfgVector& x);
		static const cfgVector cfg_sqrt(const cfgVector& x);
		static const cfgVector cfg_abs(const cfgVector& x);
		static const cfgVector cfg_to_string(const cfgVector& x);
		static const cfgVector cfg_vecmin(const cfgVector& x);
		static const cfgVector cfg_vecmax(const cfgVector& x);

		static const cfgVector cfg_min(const cfgVector& a, const cfgVector& b);
		static const cfgVector cfg_max(const cfgVector& a, const cfgVector& b);

		static const cfgVector cfg_dot_product(const cfgVector& a, const cfgVector& b);
		static const cfgVector cfg_l2norm(const cfgVector& x);
		static const cfgVector cfg_cnorm(const cfgVector& x);
		// -------------------------------------------------------------------------------------------- //
		
		// -------------------------------------------------------------------------------------------- //
		cfgVector();
		cfgVector(const cfgValue& value);
		~cfgVector();

		cfgVector(const cfgVector& x);
		const cfgVector& operator=(cfgVector x);
		void swap(cfgVector& x);
		// -------------------------------------------------------------------------------------------- //

	private:
		// data (private):
		// -------------------------------------------------------------------------------------------- //

		int size;
		int nalloc;
		static const int c_nalloc_inc = 8;

		cfgValue *value;

		char* name;	// default name = empty string = "\0"
		size_t name_memsize;		// memory handler for name string
	};
}