/*
Program WinCaml: Graphical User Interface
for interactive use of Caml-Light and Ocaml.
Copyright (C) 2005-2017 Jean Mouric 35700 Rennes France
email: jean.mouric@orange.fr

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 <http://www.gnu.org/licenses/>. 
*/

// File Utils.cpp

#include <locale>
#include <sstream>
#include <string>
#include "platform.h"

void trim(wstring& str);
wstring extension(const wstring& fileName);
size_t commonPrefix(const wstring& s1, const wstring& s2);
size_t commonSuffix(const wstring& s1, const wstring& s2);
int removeComments(wstring& str);
int mulDiv(int a, int b, int c);
void caretCoordinates(const wstring& text, size_t caretPosition, size_t spaceCountPerTab , size_t& line, size_t& column);

void trim(wstring& str)
{
	str.erase(0, str.find_first_not_of(L" \r\n\t"));
	str.erase(str.find_last_not_of(L" \r\n\t") + 1);
}

wstring extension(const wstring& fileName)
{
	size_t i = fileName.find_last_of(L'.');
	wstring ext = i > 0 ? fileName.substr(i + 1) : L"";
	if (i > 0)
	{
		wstringstream temp(wstringstream::in | wstringstream::out);
		locale loc;
		int len = (int)ext.length();
		for (int j = 0; j < len; j++)
			temp << std::toupper(ext[j],loc);
		ext = temp.str();
	}
	return ext;
}

size_t commonPrefix(const wstring& s1, const wstring& s2)
{
	size_t n = 0;
	size_t l1 = s1.length();
	size_t l2 = s2.length();
	while ( n < l1 && n < l2 && s1[n] == s2[n])
	{
		n++;
	}
	return n;

}
size_t commonSuffix(const wstring& s1, const wstring& s2)
{
	size_t n = 0;
	size_t l1 = s1.length();
	size_t l2 = s2.length();

	while( l1 > n && l2 > n && s1[l1 - n - 1] == s2[l2 - n - 1])
	{
		n++;
	}
	return n;
}
int removeComments(wstring& str)
{
	size_t d = 0;
	size_t i = 0;
	size_t j = 0;
	size_t len = str.length();
	size_t cc = 0;
	bool inString = false;
	wchar_t oc = L'\0';
	int err = -1;
	bool active = true;
	for (cc = 0; cc < len; oc = str[cc++])
	{
		if (cc < len - 1 && ((oc == L'\'' && str[cc + 1] == L'\'') || (oc == L'`' && str[cc + 1] == L'`')))
		{}
		else if (!inString)
		{
			if (str[cc] == L'"')
			{
				inString = true; active = false;
			}
		}
		else
		{
			wchar_t ch = str[cc];
			if (oc == L'\\')
			{
				if (ch ==  L'"')
				{
					if (active) {active = false;}
					else {inString = false;}
				}
				else if (ch == L'\\')
				{
					active = !active;
				}
				else
				{
					active = false;
				}
			}
			else if (ch == L'\\')
			{
				active = true;
			}
			else if (ch == L'"')
			{
				inString = false;
				active = false;
			}
		}
		if ( !inString && str[cc] == L'*' && oc == L'(')
		{
			if (d == 0) i = cc - 1;
			d++;
		}
		else if (!inString && str[cc] == L')' && oc == L'*')
		{
			if (d > 0)
				d--;
			else
			{
				err = 1;
				return err;
			}
			if (d == 0)
			{
				if ((i == 0 || (i > 0 && str[i - 1] == L'\012')) && cc < len - 1 && str[cc + 1] == L'\012')
					j = ++cc;
				else j = cc;
				size_t k = j - i + 1;
				if (k + i > len) k = len - i;
				str.erase(i, k);
				len -= k;
				if (cc >= k) cc -= k;
				else cc = 0;
			}
		}
	}
	if (d != 0)
	{
		if (inString)
		{
			str = str.substr(0, i);
			err = 2;
		}
		else
		{
			str = str.substr(0, i);
			err = 0;
		}
	}
	else if (inString)
	{
		str = str.substr(0, i);
		err = 3;
	}
	return err;
}

int mulDiv(int a, int b, int c)
{
	double x = a;
	x *= b;
	x /= c;
	return (int)(x + 0.5);
}

void caretCoordinates(const wstring& text, size_t caretPosition, size_t spaceCountPerTab , size_t& line, size_t& column)
{
	size_t i = 0, j = 0, k = 0, t = 0;
	while(k < caretPosition)
	{
		if (text[k] == L'\r')
		{
			if (k < caretPosition - 1 && text[k + 1] == L'\n') k++;
			++j;
			i = 0;
			t = 0;
		}
		else if (text[k] == L'\n')
		{
			++j;
			i = 0;
			t = 0;
		}
		else
		{
			if (text[k] == L'\t') ++t;
			else ++i;
		}
		++k;
	}
	line = j + 1;
	column = i + 1 + t * spaceCountPerTab;
}
