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

namespace AppConv.Utils{
    internal static class RadixConversion{
        private const string Characters = "0123456789ABCDEF";

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

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

            if (IsBaseValid(checkedBase)){
                return contents.Select(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{
                StringBuilder converted = new StringBuilder();

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

                    wip = wip/toBase;
                }

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