using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace gbascv
{
    class Program
    {
        static Dictionary<string, string> worddic = new Dictionary<string, string>();

        struct sWord
        {
            public string we;
            public string wj;
        };

        static sWord[] words =
        {
            new sWord{ we="LET", wj= "[ｼｷ^" },
            new sWord{ we="PRNT",  wj="[ｶｹ^" },
            new sWord{ we="END",  wj="[ｵﾜﾘ^" },
            new sWord{ we="GOTO",  wj="[ﾆｲｹ^" },
            new sWord{ we="FOR",  wj="[ﾏﾜﾚ^" },
            new sWord{ we="NEXT",  wj="[ﾄｼ|ﾙ^" },
            new sWord{ we="STOP",  wj="[ﾄﾏﾚ^" },
            new sWord{ we="IF",  wj="[ﾓｼ^" },
            new sWord{ we="THEN",  wj="[ﾅﾗﾊ|^" },
            new sWord{ we="GSUB",  wj="[@ﾖ\\|^" },
            new sWord{ we="RTN",  wj="[ｶｴﾚ^" },
            new sWord{ we="TIME",  wj="[ﾀｲﾏ^" },
            new sWord{ we="ON",  wj="[ｵﾝ^" },
            new sWord{ we="OFF",  wj="[ｵﾌ^" },
            new sWord{ we="TONE",  wj="[ｵﾄ^" },
            new sWord{ we="NO1",  wj="[ｲﾁｵﾝ^" },
            new sWord{ we="NO2",  wj="[ﾆｵﾝ^" },
            new sWord{ we="NO3",  wj="[ｻﾝｵﾝ^" },
            new sWord{ we="NO4",  wj="[ｼｵﾝ^" },
            new sWord{ we="OVFL",  wj="[ｱﾌﾚ^" },
            new sWord{ we="KEY",  wj="[ｷｲ^" },
            new sWord{ we="ANIM",  wj="[ｱﾆﾒ^" },
            new sWord{ we="TO",  wj="[ｶﾗ^" },
        };

        static sWord[] words2 =
        {
            new sWord{ we="RAND(",  wj="[ﾗﾝｽｳ^(" },
            new sWord{ we="CELL(",  wj="[ｾﾙ^(" },
            new sWord{ we="POST(",  wj="[ｲﾁ^(" },
            new sWord{ we="HORZ(",  wj="[ﾖｺ^(" },
            new sWord{ we="VERT(",  wj="[ﾀﾃ^(" },
        };

        static void Main(string[] args)
        {
            if (args.Length != 1)
            {
                Console.WriteLine("usage: gbascv <infile(text)>");
                return;
            }

            var infile = args[0];
            if(!Path.IsPathRooted(infile))
            {
                infile = Path.Combine(System.IO.Directory.GetCurrentDirectory(), infile);
            }

            var outfile_en = infile + ".en.txt";
            var outfile_jp = infile + ".jp.txt";
            var lines = new List<string>();
            try
            {
                using (var sr = new StreamReader(infile, Encoding.GetEncoding("Shift_JIS")))
                {
                    string line = null;
                    while ((line = sr.ReadLine()) != null)
                    {
                        line = line.Trim();
                        var comment = line.IndexOf("//");
                        if (comment >= 0)
                        {
                            line = line.Substring(0, comment);
                        }
                        if (line.Length == 0) continue;
                        line = line.ToUpper();
                        lines.Add(line);
                    }
                }

                // 英語版
                {
                    var sb = new StringBuilder();
                    foreach (var s in lines)
                    {
                        sb.AppendLine(s);
                        File.WriteAllText(outfile_en, sb.ToString(), Encoding.GetEncoding("Shift_JIS"));
                    }
                }
                // 日本語版
                using (var sw = new StreamWriter(outfile_jp, false, Encoding.GetEncoding("Shift_JIS")))
                {
                    foreach (var s in lines)
                    {
                        sw.WriteLine(ConvertJp(s));
                    }
                }
            }
            catch(Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        /// <summary>
        /// 日本語BASICに変換
        /// </summary>
        /// <param name="src"></param>
        /// <returns></returns>
        static string ConvertJp(string src)
        {
            // スペースで区切った単語単位の置換
            var sp = src.Split(' ');
            var items = new List<string>(sp);
            for(int i = 0; i < items.Count; i++)
            {
                foreach (var w in words)
                {
                    if (items[i] == w.we)
                    {
                        items[i] = w.wj;
                        break;
                    }
                }
            }

            if (sp.Length > 2)
            {
                switch(sp[1])
                {
                    case "GOTO":
                        // FALLTHROUGH
                    case "GSUB":
                        {
                            var tmp = items[1];
                            items[1] = items[2];
                            items[2] = tmp;
                        }
                        break;
                    case "IF":
                        items.Add("[ﾆｲｹ^");
                        break;

                    case "FOR":
                        {
                            var len = items.Count;
                            items.Insert(len - 1, "[ｶﾝｶｸ^");
                        }
                        break;

                    default:
                        break;
                }
            }
            var sb = new StringBuilder();
            sb.Append("^");
            for(var i = 0; i < items.Count; i++)
            {
                sb.Append(items[i]);
                if(i < items.Count - 1)
                {
                    var is_kana0 = IsKana(items[i]);
                    var is_kana1 = IsKana(items[i + 1]);
                    if (is_kana0 != is_kana1)
                    {
                        continue;
                    }
                    sb.Append(" ");
                }
            }
            var dst = sb.ToString().Trim();
            foreach(var w in words2)
            {
                dst = dst.Replace(w.we, w.wj);
            }
            return dst;
        }

        static bool IsKana(string str)
        {
            foreach(var c in str)
            {
                if(c >= 0xa0)
                {
                    return true;
                }
            }
            return false;
        }

        static string SwapStr(string src, int index1, int index2)
        {
            var s = src.Split(' ');
            if(s.Length > index1 && s.Length > index2)
            {
                var tmp = s[index1];
                s[index1] = s[index2];
                s[index2] = tmp;
            }
            var sb = new StringBuilder();
            foreach(var ss in s)
            {
                sb.Append(ss);
                sb.Append(' ');
            }
            var ret = sb.ToString().Trim();
            return ret;
        }
    }
}
