#include "zavorky.h"

std::string remove_parantheses(const std::string& line);
std::string parse_line(const std::string& line); //purges whitespace


int process_line(const std::string& in_line)
{
	std::string line = parse_line(in_line);
	std::string outline = remove_parantheses(line);
	std::cout << outline << std::endl;
	return 0;
}

std::string parse_line(const std::string& line) //purges whitespace
{
	std::string outline = "";
	for (size_t i = 0; i < line.size(); i++)
	{
		if (isdigit(line[i])) return ""; // no numerals allowed
		if (!isspace(line[i]))			 // no spaces
		{
			outline += line[i];
		}
	}
	return outline;
}

bool is_mono(const std::string& expr) // is monolithic bloc
{
	// a*b/c is ok
	// a+b/c is not
	// but a*(b+c)*d is also
	int par_lvl = 0;
	if (expr[0] == '/')
	{
		return false;
	}
	for (size_t i = 1; i < expr.size(); i++)
	{
		char znak = expr[i];
		if ((znak == '+' or znak == '-') and par_lvl <= 1)
		{
			return false;
		}
		if (znak == '(')
		{
			par_lvl++;
		}
		if (znak == ')')
		{
			par_lvl--;
		}
	}
	return true;
}

std::string remove_parantheses(const std::string& line)
{
	// go through line and find redundant parantheses
	int par_lvl = 0;
	int max_par_lvl = 0;
	std::string out_string = line;
	std::string wip_string = "";

	while (out_string != wip_string) // i might have to remove in waves
	{
		wip_string = out_string;
		out_string = "";
		std::vector<bool> purge_param;
		std::vector<size_t> param_beg;

		// first go through file and find redundant parantheses
		for (size_t i = 0; i < wip_string.size(); i++)
		{
			if (wip_string[i] == '(')
			{
				bool purge;

				if (i == 0) // opening parantheses at the beginning
				{
					purge = true; // redundant parantheses
				}// i = 0
				else
				{
					if (wip_string[i - 1] == '+')
					{
						purge = true; // + before parantheses => redundant
					}
					else
					{
						purge = false; // *,-,/ before parantheses => important
					}
					if (isalnum(wip_string[i-1]))
					{
						return ""; // variable without operation in front of bracket
					}
				} // i != 0

				if (par_lvl < max_par_lvl) // if on already visited level, just modify parameters
				{
					purge_param[par_lvl] = purge;
					param_beg[par_lvl] = i;
				}
				else // if on new level, pushback
				{
					purge_param.push_back(purge);
					param_beg.push_back(i);
				}

				par_lvl++;
				max_par_lvl++;
			} // char = (

			if (wip_string[i] == ')')	// closing parantheses
			{
				par_lvl--;
				if (par_lvl < 0) // mismatched parantheses
				{
					return "";
				}
				if (i == wip_string.size() - 1) // closing at the end of line
				{
					purge_param[par_lvl] = purge_param[par_lvl] and true;
				}
				else
				{
					if (wip_string[i + 1] == '+' or wip_string[i + 1] == '-' or wip_string[i + 1] == ')')
					{
						purge_param[par_lvl] = purge_param[par_lvl] and true;
					}
					else
					{
						purge_param[par_lvl] = false;
					}
					if (isalnum(wip_string[i+1]))
					{
						return "";
					}
				}
				// if the expression in the parantheses is a bloc (a*b/c*d) then i can remove them independently
				std::string expr;
				size_t beg_of_purge_param = param_beg[par_lvl];

				if (beg_of_purge_param == 0)
				{
					expr = wip_string.substr(beg_of_purge_param, i - beg_of_purge_param);
				}
				else
				{
					expr = wip_string.substr(beg_of_purge_param - 1, i - beg_of_purge_param);
				}

				purge_param[par_lvl] = purge_param[par_lvl] or is_mono(expr);

				if (purge_param[par_lvl]) // remove parantheses, replace strings with new version and move iterator to new position
				{
					std::string pre_par = wip_string.substr(0, beg_of_purge_param);	//before parntheses
					std::string par_con = wip_string.substr(beg_of_purge_param + 1, i - beg_of_purge_param - 1); // expression in parantheses
					std::string post_par = wip_string.substr(i + 1);	//after parantheses
					out_string = pre_par + par_con + post_par;
					wip_string = out_string;
					i -= 2;	// removed opening and closing bracket, so move iterator two steps back
				}
			} // char = )
			if (out_string == "") // if nothing was removed, exit on while condition
			{
				out_string = wip_string;
			}
		} // find redundancy

		if (par_lvl != 0) //mismatched parantheses
		{
			return "";
		}
	}
	return out_string;
}