using System;
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine.UI;

public class User
{
    enum GetUserFlags { CompanyID, UserID };
    public uint id { get; set; }
    public string name { get; set; }
    public bool online { get; set; }

    public Toggle toggle { get; set; }
    public GameObject toggle_user { get; set; }
    public GameObject marker { get; set; }
    public LineRenderer marker_line { get; set; }
    //public uint acc_id { get; set; }
    //public bool starting { get; set; }
    public bool broadcast { get; set; }


    public static void UsersReceive(byte[] bytedata)
    {
        Debug.Log("UsersReceive");
        var player = PlayerController.instance;
        player.users = new Dictionary<uint, User>();
        int read = 5;
        while (read < bytedata.Length)
        {
            var id = BitConverter.ToUInt32(bytedata, read);
            var online = bytedata[read + 4];
            var lenname = bytedata[read + 5];
            var name = Encoding.UTF8.GetString(bytedata, read + 6, lenname);
            read += 6 + lenname;
            Debug.Log($"user received id {id} lenname {lenname} name {name} online {online}");
            player.users.Add(id, new User { id = id, name = name, online = online!=0 });
            WorkerMarker(player.users[id], Color.green);
        }
        player.users_load = true;
    }

    public static void SendGetUsers()
    {
        SendGetUsersForCompany(Client.instance.company_id);
    }
    
    //companyId: 1 = Тайшет, 2 = Тестовая, 3 = Братское
    public static void SendGetUsersForCompany(uint companyId)
    {
        List<byte> list = new List<byte>();
        list.Add(47);
        list.Add((byte)GetUserFlags.CompanyID);
        list.AddRange(BitConverter.GetBytes(companyId));
        Client.SendEnqueue(list.ToArray());
    }

    public static void SendGetUser(uint userId)
    {
        List<byte> list = new List<byte>();
        list.Add(47);
        list.Add((byte)GetUserFlags.UserID);
        list.AddRange(BitConverter.GetBytes(userId));
        Client.SendEnqueue(list.ToArray());
    }

    public static User Find(uint id)
    {
        User user;
        PlayerController.instance.users.TryGetValue(id, out user);
        return user;
    }

    public static void LogInOut(byte[] bytedata)
    {
        var accid = BitConverter.ToUInt32(bytedata, 1);
        var cmd = bytedata[5];

        var u = User.Find(accid);

        if (u != null)
        {
            var b = cmd != 0;
            u.toggle_user.SetActive(b);
            u.marker.SetActive(b);
        }
        else
        {
            Debug.LogError($"LogInOut accid {accid} not found");
            SendGetUser(accid);
        }

        Debug.Log($"LogInOut accid {accid} cmd {cmd}");
    }

    public static void CoordinatesReceive(byte[] bytedata)
    {
        //var coordleng = bytedata.Length - 11;
        var accid = BitConverter.ToUInt32(bytedata, 5);
        var locid = BitConverter.ToUInt32(bytedata, 9);
        var player = PlayerController.instance;
        //WorkerController.TestStructures.Clear();
        //print("len " + BitConverter.ToUInt32(bytedata, 1));
        var worker = new List<Structure>();
        for (var read = 13; read < bytedata.Length; read += 20)
        {
            var id = BitConverter.ToUInt32(bytedata, read);
            var x = BitConverter.ToSingle(bytedata, read + 4);
            var y = BitConverter.ToSingle(bytedata, read + 8);
            var ticks = BitConverter.ToInt64(bytedata, read + 12);
            //print($"coord accid {accid} locid {locid} {id} x {x} y{y} ticks {ticks}");

            //WorkerController.markers.ElementAt(1).marker.transform.position = new Vector3(x, 0.5f, y); 

            //WorkerController.TestStructures
            worker.Add(new Structure
            {
                id = id,
                coord_x = x,
                coord_y = y,
                ts = new DateTime(ticks),
                acc_id = accid,
                location_id = locid,
                zone_id = 1
            });
        }
        player.Workers[accid] = worker.OrderBy(w => w.ts).ToList();
        player.end_send[accid] = true;
    }

    /// <summary>
    /// Создание маркера для сотрудника
    /// </summary>
    /// <param name="acc_id"></param>
    public static void WorkerMarker(User user, Color color/*, GameObject WorkersList, Action<uint> BroadcastStart*/)
    {
        var toggle_user = UnityEngine.Object.Instantiate(Resources.Load("GameObjects/ToggleUser", typeof(GameObject))) as GameObject;
        toggle_user.name = $"{user.id}";
        var toggle = toggle_user.transform.GetChild(0).GetComponent<Toggle>();
        toggle.transform.GetChild(1).gameObject.GetComponent<Text>().text = $"{user.id} {user.name}";
        //toggle_user.transform.SetParent(WorkersList.transform);
        toggle.isOn = false;
        //var camera_button = toggle_user.transform.GetChild(1).GetComponent<Button>();
        //camera_button.onClick.AddListener(() => BroadcastStart(user.id));


        var marker = UnityEngine.Object.Instantiate(Resources.Load("GameObjects/Capsule", typeof(GameObject))) as GameObject;
        marker.name = $"marker_{user.id}";
        marker.transform.GetChild(0).transform.GetChild(0).transform.GetChild(0).GetComponent<Text>().text = $"{user.id}";
        marker.transform.SetParent(GameObject.Find("Markers").transform);
        marker.GetComponent<Renderer>().material.color = color; // UnityEngine.Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f);
        marker.GetComponent<LabelObjectScript>().UserId = user.id;

        var color_line = UnityEngine.Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f);
        var marker_line = UnityEngine.Object.Instantiate(Resources.Load("GameObjects/Line", typeof(LineRenderer))) as LineRenderer;
        marker_line.name = $"marker_line_{user.id}";
        marker_line.startColor = color_line;
        marker_line.endColor = Color.white;
        marker_line.material.color = color_line;
        marker_line.transform.SetParent(GameObject.Find("Markers").transform);

        user.marker = marker;
        user.toggle = toggle;
        user.marker_line = marker_line;
        user.toggle_user = toggle_user;
    }

    public void SetParam(GameObject WorkersList, Action<uint> BroadcastStart)
    {
        toggle_user.transform.SetParent(WorkersList.transform);
        var camera_button = toggle_user.transform.GetChild(1).GetComponent<Button>();
        camera_button.onClick.AddListener(() => BroadcastStart(id));
    }    
}