using System;
using System.Globalization;
using System.Linq;
using System.Text;

namespace AppConv.Utils;

static class RadixConversion {
	private const string Characters = "0123456789ABCDEF";

	public static bool IsBaseValid(int checkedBase) {
		return checkedBase is >= 1 and <= 16;
	}

	public static bool IsNumberValid(string contents, int checkedBase) {
		if (checkedBase == 1) {
			return contents.All(static chr => chr == '1');
		}

		if (IsBaseValid(checkedBase)) {
			return contents.Select(static chr => Characters.IndexOf(char.ToUpper(chr))).All(index => index != -1 && index < checkedBase);
		}

		return false;
	}

	public static string Do(string contents, int fromBase, int toBase) { // TODO biginteger
		if (fromBase == 1) {
			contents = contents.Length.ToString(CultureInfo.InvariantCulture);
			fromBase = 10;
		}

		long wip;

		if (fromBase == 10) {
			wip = long.Parse(contents, NumberStyles.None, CultureInfo.InvariantCulture);
		}
		else {
			wip = 0;

			for (int chr = 0; chr < contents.Length; chr++) {
				int index = Characters.IndexOf(char.ToUpperInvariant(contents[chr]));

				if (index > 0) {
					wip += index * (long) Math.Pow(fromBase, contents.Length - chr - 1);

					if (wip < 0) {
						throw new OverflowException();
					}
				}
			}
		}

		if (toBase == 1) {
			if (wip <= int.MaxValue) {
				return new string('1', (int) wip);
			}
			else {
				throw new OverflowException();
			}
		}
		else if (wip < toBase) {
			return Characters[(int) wip].ToString();
		}
		else {
			var converted = new StringBuilder();

			while (wip >= toBase) {
				int index = (int) (wip % toBase);
				converted.Insert(0, Characters[index]);

				wip /= toBase;
			}

			return converted.Insert(0, Characters[(int) wip]).ToString();
		}
	}
}