using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace WpfApp1.Tools
{
    internal class MaskTools
    {
        public static void rleInit(ref RLE R, int h, int w, int m, uint[]? cnts)
        {
            R = new RLE { h = h, w = w, m = m, cnts = (m == 0) ? (new uint[1]) : (new uint[m]) };
            if (cnts != null)
            {
                for (int i = 0; i < m; i++)
                {
                    R.cnts[i] = cnts[i];
                }
            }
        }

        public static void rlesInit(ref RLE[] Rs, int n)
        {
            Rs = new RLE[n];
            for (int i = 0; i < n; i++)
            {
                rleInit(ref Rs[i], 0, 0, 0, null);
            }
        }

        public static void rleEncode(ref RLE[] Rs, byte[] M, int h, int w, int n)
        {
            int i, j, k, a = w * h;
            uint c;
            uint[] cnts;
            byte p;
            cnts = new uint[a + 1];
            for (i = 0; i < n; i++)
            {
                int Ti = a * i;
                k = 0;
                p = 0;
                c = 0;
                for (j = 0; j < a; j++)
                {
                    if (M[Ti + j] != p)
                    {
                        cnts[k++] = c;
                        c = 0;
                        p = M[Ti + j];
                    }
                    c++;
                }
                cnts[k++] = c;
                rleInit(ref Rs[i], h, w, k, cnts);
            }
        }

        public static void rleDecode(RLE[] Rs, byte[] M, int n)
        {
            int m = 0;
            for (int i = 0; i < n; i++)
            {
                byte v = 0;
                for (int j = 0; j < Rs[i].m; j++)
                {
                    for (int k = 0; k < Rs[i].cnts[j]; k++)
                    {
                        M[m++] = v;
                    }
                    v = (byte)(1 - v);
                }
            }
        }

        public static string rleToString(RLE R)
        {
            int i, m = R.m, p = 0;
            long x;
            int more;
            char[] s = new char[m * 6];
            for (i = 0; i < m; i++)
            {
                x = R.cnts[i];
                if (i > 2)
                {
                    x -= R.cnts[i - 2];
                }
                more = 1;
                while (more != 0)
                {
                    char c = (char)(x & 0x1f);
                    x >>= 5;
                    more = (c & 0x10) != 0 ? x != -1 ? 1 : 0 : x != 0 ? 1 : 0;
                    if (more != 0)
                    {
                        c |= (char)(0x20);
                    }
                    c += (char)(48);
                    s[p++] = c;
                }
            }
            s[p] = (char)(0);
            return new string(s);
        }

        public static void rleFrString(ref RLE R, string s, int h, int w)
        {
            int m = 0, p = 0, k;
            long x;
            int more;
            uint[] cnts;
            m = s.Length;
            cnts = new uint[m];
            m = 0;
            while (p < s.Length)
            {
                x = 0;
                k = 0;
                more = 1;
                while (more != 0)
                {
                    char c = (char)(s[p] - 48);
                    x |= (c & 0x1f) << (5 * k);
                    more = c & 0x20;
                    p++;
                    k++;
                    if (more == 0 && (c & 0x10) != 0)
                    {
                        x |= -1 << (5 * k);
                    }
                }
                if (m > 2)
                {
                    x += cnts[m - 2];
                    if (x < 0)
                    {
                        Trace.WriteLine("x: " + x.ToString());
                    }
                }
                if (x != (uint)x)
                {
                    Trace.WriteLine("x: " + x.ToString() + "  (uint)x: " + ((uint)x).ToString());
                }
                cnts[m++] = (uint)x;
            }
            rleInit(ref R, h, w, m, cnts);
        }
    }
}
