#pragma once
/*
 *  Copyright (C) 2024  Brett Terpstra
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef BLT_LOGGING_STATUS_H
#define BLT_LOGGING_STATUS_H

#include <mutex>
#include <string>
#include <blt/logging/injector.h>
#include <blt/math/vectors.h>
#include <blt/std/types.h>

namespace blt::logging
{
	class status_bar_t;

	class status_item_t
	{
	public:
		virtual ~status_item_t() = default;

		void assign(status_bar_t* bar)
		{
			m_status = bar;
		}

		[[nodiscard]] virtual i32 lines_used() const
		{
			return 1;
		}

		[[nodiscard]] virtual std::string print(vec2i screen_size, i32 max_printed_length) const = 0;
	protected:
		status_bar_t* m_status = nullptr;
	};

	class status_progress_bar_t final : public status_item_t
	{
	public:
		[[nodiscard]] std::string print(vec2i screen_size, i32 max_printed_length) const override;

		void set_progress(double progress);

		void add_progress(const double progress)
		{
			set_progress(get_progress() + progress);
		}

		[[nodiscard]] double get_progress() const
		{
			return m_progress;
		}
	private:
		double m_progress = 0.0;
	};

	class status_bar_t final : public injector_t
	{
	public:
		explicit status_bar_t();

		injector_output_t inject(const std::string& input) override;

		status_bar_t& add(status_item_t& item)
		{
			item.assign(this);
			m_status_items.push_back(&item);
			compute_size();
			return *this;
		}

		void redraw() const;

		~status_bar_t() override;
	private:
		void compute_size();

		std::vector<status_item_t*> m_status_items;
		i32 m_status_size = 0;
		i32 m_max_printed_length = 0;
		vec2i m_screen_size;
		vec2i m_last_log_position;
		vec2i m_begin_position;

		std::mutex m_print_mutex;
	};

}

#endif //BLT_LOGGING_STATUS_H