using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
using UnityEngine.Rendering;
using Unity.Collections;

[RequireComponent(typeof(Camera))]
[ExecuteInEditMode]
public class DepthCamera : MonoBehaviour
{
    private Queue<AsyncGPUReadbackRequest> requests = new Queue<AsyncGPUReadbackRequest>();

    public float timeBetweenRequests = 0.2f;
    public string topicname = "rt/depth_image/image_raw/compressed";
    public string frame_id = null;
    public ComputeShader shader;

    //private ImagePublisher ImagePub;
    private RenderTexture m_RenderTexture;
    private float timer = 0.0f;
    //private Image_ myimage = new Image_(); // format 32 bits floating point for depth camera
    
    //NativeArray<float> _buffer;
    private ComputeBuffer buffer;
    private float[] output;
    private int kernel;

    void Start()
    {
        //ImagePub = new ImagePublisher(topicname);

        Camera MyCamera = GetComponent<Camera>();
        MyCamera.depthTextureMode = MyCamera.depthTextureMode | DepthTextureMode.Depth;
        m_RenderTexture = MyCamera.targetTexture;
        m_RenderTexture.depth = 32;
        m_RenderTexture.enableRandomWrite = true; // ik wijzig texture niet dus niet nodig
        MyCamera.Render();

        Debug.Log("In depthcamera, depth: " + m_RenderTexture.depth.ToString());

        //myimage.encoding_ = "32FC1";
        //myimage.height_ = (uint) m_RenderTexture.height;
        //myimage.width_ = (uint) m_RenderTexture.width;
        //myimage.is_bigendian_ = 0;
        //myimage.step_ = myimage.width_; //? even kijken of dit okay is

        Debug.Log("In depthcamera, camsize width:" + m_RenderTexture.width.ToString() + " height:" + m_RenderTexture.height.ToString());

        buffer = new ComputeBuffer(m_RenderTexture.width * m_RenderTexture.height, sizeof(float)); 
        //_buffer = new NativeArray<float>(m_RenderTexture.height * m_RenderTexture.width, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);

        kernel = shader.FindKernel("CSMain");
        shader.SetTexture(kernel, "tex", m_RenderTexture);
        shader.SetBuffer(kernel, "output", buffer);
    }

    void Update()
    {
       
        // Handle Request Timer
        timer += Time.deltaTime;
        if (timer > timeBetweenRequests)
        {
            shader.Dispatch(kernel, m_RenderTexture.width/8, m_RenderTexture.height/8, 1);
            //buffer.GetData(output);

            Debug.Log(output.ToString());
            timer = timer - timeBetweenRequests;
            //AsyncGPUReadbackRequest rq = AsyncGPUReadback.RequestIntoNativeArray(ref _buffer, buffer);
            //requests.Enqueue(rq);

            //myimage.data_ = GetBytes(output);
            //myimage.header_.stamp_ = ros_helper.RosHelper.GetUnixTimestamp();
            //myimage.header_.frame_id_ = frame_id;
            //ImagePub.Publish(myimage);
        }
    }

    /*void ReadbackData(AsyncGPUReadbackRequest request)
    {

        var input = request.GetData<float>().ToArray();  //float is 32 bits

        //Debug.Log("Got a AsyncGPUReadbackRequest with size " + input.Length.ToString() + " and require size " + (MyCamera.pixelWidth * MyCamera.pixelHeight).ToString() + ", discarding it");
      
        myimage.data_ = GetBytes(input);
        myimage.header_.stamp_ = ros_helper.RosHelper.GetUnixTimestamp();
        myimage.header_.frame_id_ = frame_id;
        ImagePub.Publish(myimage);
    }*/

    private byte[] GetBytes(float[] input)
    {
        byte[] messageinput = new byte[input.Length * 4];
        for (int i = 0; i < input.Length; i++)
        {
            byte[] newbytes = BitConverter.GetBytes(input[i]);
            for (int j = 0; j < newbytes.Length; j++)
            {
                messageinput[i * 4 + j] = newbytes[j];
            }
        }
        return messageinput;
    }

    private void OnDisable()
    {
        //ImagePub.Cleanup();
    }

    private void OnDestroy()
    {
        //buffer.Dispose();
    }
}
