using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;

public static class TextUtils
{
    public static List<TextToken> ParseText(byte[] textData, int startOffset)
    {
        List<TextToken> tokens = new List<TextToken>();
        int offset = startOffset;

        while (offset < textData.Length && textData[offset] != 0)
        {
            ushort code = ReadUInt16(textData, ref offset);

            if ((code & 0x1000) != 0) // Это команда
            {
                ParseCommand(code, textData, ref offset, tokens);
                if (tokens.Last().Value == "end") return tokens;    //If end of window
            }
            else if ((code & 0x2000) != 0) // My russian text
            {
                offset += 2;
                ParseText(code, textData, ref offset, tokens);
            }
            else
            {
                // Japanese and other char
                offset += 2;
                string chr = (code <= 255 && code >= 32) ? "" + (char)code : $"[{code:X4}]";
                tokens.Add(new TextToken { Key = "text", Value = chr });
            }
        }

        return tokens;
    }

    private static void ParseCommand(ushort code, byte[] data, ref int offset, List<TextToken> tokens)
    {
        ushort commandType = (ushort)(code & 0x00FF);

        TextToken token = new TextToken();

        offset += 2;

        switch (commandType)
        {
            case 0x1D: // color
                token.Key = "color";
                token.Value = ReadUInt16(data, ref offset).ToString();
                break;

            case 0x12: // name
                token.Key = "text";
                token.Value = "Суоуоуов";  //TODO: take from global vars
                break;

            case 0x13: // surname
                token.Key = "text";
                token.Value = "Вася"; //TODO: take from global vars
                break;

            case 0x20: // tab
                token.Key = "cmd";
                token.Value = "tab";
                break;

            case 0x02: // wipe text & reset coords
                token.Key = "cmd";
                token.Value = "wipe";
                break;

            case 0x03: // end
                token.Key = "cmd";
                token.Value = "end";
                break;

            case 0x05: // pause
                token.Key = "pause";
                token.Value = ReadUInt16(data, ref offset).ToString();
                break;


            case 0x06: // wait input
                token.Key = "cmd";
                token.Value = "wait_input";
                break;

            case 0x08: // wait input
                token.Key = "user_selection";
                token.Value = ReadUInt16(data, ref offset).ToString();
                break;

            case 0x09: // wait input
                token.Key = "cmd";
                token.Value = "wait_selection";
                break;

            case 0x01: // newline
                token.Key = "cmd";
                token.Value = "newline";
                break;

            default:
                token.Key = "unknown";
                token.Value = commandType.ToString("X4");
                break;
        }
        offset += (((code & 0x0F00) >> 8) - 1) * 2;  //Original offset after command
        tokens.Add(token);
    }

    private static void ParseText(ushort code, byte[] data, ref int offset, List<TextToken> tokens)
    {
        int length = code & 0x00FF;
        TextToken token = new TextToken
        {
            Key = "text",
            Value = Encoding.GetEncoding(1251).GetString(data, offset, length).Replace("~", "...")
        };

        offset += length;

        // Выравнивание по 2 байта
        offset += length & 1;


        tokens.Add(token);
    }

    private static ushort ReadUInt16(byte[] data, ref int offset)
    {
        ushort value = (ushort)(data[offset] | (data[offset + 1] << 8));
        return value;
    }
}

public class TextToken
{
    public string Key { get; set; }
    public string Value { get; set; }

    public override string ToString() => $"{Key}: {Value}";
}