using System;
using System.Collections.Generic;
using System.IO;
using Unity.Collections;
using UnityEngine;
using UnityEngine.UI;

public class WhiteBoradServer : MonoBehaviour
{
    float serverSendNextTiming; //T[o[ŁATime.timeA̎ԈȏɂȂ𔭐MB 
    const int width = 360;// RawImageɐݒ肷Texture2D̃TCY
    const int height = 360;
    const string filePath = "white_board.bin";
    Dictionary<string, Color32> colorMap = new Dictionary<string, Color32>(){
        {"R", new Color32(255, 0, 0, 255)},  {"G", new Color32(0, 255, 0, 255)},
        {"B", new Color32(0, 0, 255, 255)},  {"W", new Color32(255, 255, 255, 255)}
    };
    public static int brushSize = 3;// LF̂̃TCŶ`uVƂĎg
    RawImage rawImage;// CanvasςɔzuRawImageŁA`Ώ

    void Start()
    {
        Time.fixedDeltaTime = 0.02f;//Application.targetFrameRate = 50;ɑŒt[Ԋuw

        TcpAppServer.onGUI_width = 300;//OnGUI()Ŏg\ύX
        TcpAppServer.onGUI_TextFieldFontSize = 24;//OnGUI()Ŏg\TCXύX
        TcpAppServer.onGUI_LabelFontSize = 14;
        TcpAppServer.onGUI_ButtonFontSize = 16;
        TcpAppServer.onGUI_flagClient = false;// T[oponGUIʂgiNCAgsvj

         TcpCommunication.tcp_port = 51234;// T[oŎg|[gԍisɕύX\j

        TcpAppServer.onTcpServerStart += (server) =>
        {// T[oN̏
            TcpAppServer.onGUI_flagServer = false;// T[opOnGUI\
        };

        TcpAppServer.onAcceptTcp += (client) =>
        {// ڑĂNCAgւACCSEPT̏
            //TcpAppServer.onGUI_flag = false;// trueŐڑ̃fobN\
        };

        TcpAppServer.onReceive += (TcpCommunication com, BinPacket msg) =>
        {   // NCAĝ̎Mi̗ł́Amsg̕Mj
            string[] datas = msg.ToString().ToUpper().Split(",");// M "RED,100,20"ŁAFxy̍W
            if (datas.Length != 3)
            {
                TcpAppServer.onGUI_message = $"onReceive̎MG[:{msg.ToString()}";
                return;
            }
            Color32 color = new Color32(0, 0, 0, 255);// ` 
            string colorkey = datas[0].Length > 0 ? datas[0].Substring(0,1) : "X";
            if (colorMap.ContainsKey(colorkey)) color = colorMap[colorkey];//M擪F擾
            int x = int.Parse(datas[1]);
            int y = int.Parse(datas[2]);
            draw(color,  x,  y);
        };

        GameObject rawImageObj = GameObject.Find("RawImage");
        this.rawImage = rawImageObj.GetComponent<RawImage>();// `ΏۂRawImageCX^XϐɃZbg
        Color32 color = new Color32(255, 255, 255, 255);
        this.rawImage.texture = createTexture(width, height, color);// colorFTexture2D𐶐;

        // filePath̃t@C݂΁Ãt@Ceŏ\
        FileInfo fileInfo = new FileInfo(filePath);
        if (false && fileInfo.Exists)
        {
            byte[] buff = new byte[fileInfo.Length];// t@CeLobt@
            using (FileStream stream = File.Open(filePath, FileMode.Open))
            {
                int idx = 0;
                while (idx < buff.Length)
                {
                    idx += stream.Read(buff, idx, buff.Length - idx);// t@Cǂݍ
                }
            }
            Texture2D texture = (Texture2D)this.rawImage.texture;
            Color32[] pixels = texture.GetPixels32();
            BytesToColor32(buff, pixels);// texturePixels32zbuffZbg
            texture.SetPixels32(pixels);// ʍXV
            texture.Apply();
        }
    }

    void FixedUpdate()
    {
        if (Input.GetMouseButton(1))// E{^ŏ
        {
            this.rawImage.texture = createTexture(width, height, new Color32(255, 255, 255, 255));
        }

        bool sendTiming = Time.time >= this.serverSendNextTiming;
        if (sendTiming == false) return;// NCAgւ̃C[WM^C~O
        this.serverSendNextTiming = Time.time + 0.01f; // 10~bƂɑM(̑M^C~O)

        // T[o[̉ʂ̑M擾
        Texture2D texture = (Texture2D)this.rawImage.texture;
        Color32[] pixels = texture.GetPixels32();
        byte[] sendBuffer = getBytesByPixels(pixels);

        // ڑĂNCAgׂĂɑM
        for (int i = 0; i < TcpAppServer.instance.clientlist.Count; i++)
        {
            TcpCommunication com = TcpAppServer.instance.clientlist[i];
            if (com == null || com.isRecRunning == false) continue;
            com.SendMessage(sendBuffer); // NCAgɑM
        }
    }

    // this.rawImage.textureɁAcolorFŁi x,  y )ʒubrushSize̐``
    private void draw(Color32 color, int x, int y)
    {
        int idx = y * height + x;// NbNʒuTexture2D̃sNZwFɕύXB
        Texture2D texture = (Texture2D)this.rawImage.texture;
        Color32[] pixels = texture.GetPixels32();
        try
        {
            for (int y2 = 0; y2 < brushSize; y2++)
            {
                for (int x2 = 0; x2 < brushSize; x2++)
                {
                    pixels[idx + x2 + y2 * width] = color;
                }
            }
        }
        catch (Exception _) { }
        texture.SetPixels32(pixels);
        texture.Apply();
    }


    public void OnApplicationQuit()// vOIɁASerializeStrVector3IuWFNgt@C
    {
        Texture2D texture = (Texture2D)this.rawImage.texture;
        byte[] buff = getBytesByPixels(texture.GetPixels32());
        using (FileStream stream = File.Open(filePath, FileMode.Create))
        {
            stream.Write(buff, 0, buff.Length);// t@Cɏ
        }
    }

    // // colorFŁAwidth ~ height̃TCYTexture2D𐶐B
    public static Texture2D createTexture(int width, int height, Color32 color)
    {
        Texture2D texture = new Texture2D(width, height, TextureFormat.RGBA32, false);
        NativeArray<Color32> pixels = texture.GetRawTextureData<Color32>();
        Debug.Log($"{pixels.Length}  ( {texture.height}, {texture.width})");
        for (int i = 0; i < pixels.Length; i++)
        {
            pixels[i] = color;
        }
        texture.Apply();
        return texture;
    }

    // bytezŁATexture2D擾pixelszݒ肷ioCi摜ݒj
    public static void BytesToColor32(byte[] bytes, Color32[] pixels)
    {
        bool chk = bytes.Length == pixels.Length * 4;
        if (chk == false) throw new Exception("BytesToColor32: {bytes.Length]bytepixelsɐݒo܂B");
        for (int idx_bytes = 0, idx = 0; idx < pixels.Length; idx++)
        {
            byte r = bytes[idx_bytes++];
            byte g = bytes[idx_bytes++];
            byte b = bytes[idx_bytes++];
            byte a = bytes[idx_bytes++];
            pixels[idx] = new Color32(r, g, b, a);
        }
    }

    // Texture2D擾pixelsz񂩂bytez񂩂𐶐ĕԂBi摜̃oCij
    public static byte[] getBytesByPixels(Color32[] pixels)
    {
        byte[] bytes = new byte[pixels.Length * 4];
        for (int i = 0, idx_bytes = 0; i < pixels.Length; i++)
        {
            bytes[idx_bytes++] = pixels[i].r;
            bytes[idx_bytes++] = pixels[i].g;
            bytes[idx_bytes++] = pixels[i].b;
            bytes[idx_bytes++] = pixels[i].a;
        }
        return bytes;
    }
}

