using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class RenderText : MonoBehaviour
{
    int frame = 60;
    public int m_CaptureFrameRate;
    public string outputDirectory = "SampleRecordings/Projection";

    [HideInInspector]
    public Texture2D texture;

    public ProjectionType m_ProjectionType = ProjectionType.Gnomic;

    public bool m_Record = false;

    

    int txt_W;
    int txt_H;

    public int m_RecordedFrames;

    public Material material;

    float x_FOV;
    float y_FOV;
    float y_Rotation;
    float x_Rotation;
    float y_Divide;
    float x_Divide;

    string m_Timestamp;

    GameObject m_CubeMapPrefab = null;

    List<Shader> m_ShaderList = new List<Shader>();

    public enum ProjectionType
    {
        Cropped,
        CroppedFOV,
        Squeezed,
        Gnomic
    }

    private void Awake()
    {
        SetupMatShaders();
        m_RecordedFrames = 0;
    }

    // Initial configuration for frame rate
    private void Start()
    {
        SetupFrameRateConfiguration();
        
    }

    private void Update()
    {
        ToggleRecording();

        if (m_Record)
        {
            for (int frameCount = 0; frameCount < 4; frameCount++)
            {
                SetMaterialParametersBasedOnProjectionType(frameCount);
            }

            m_RecordedFrames++;

        }
        else
        {
            m_RecordedFrames = 0;
        }

        frame++;
    }

    void SetMaterialParametersBasedOnProjectionType(int frameCount)
    {
        var m_HeightY = 0f;

        if (frameCount == 0 || frameCount == 2)
        {
            // Set Front & Back
            if(m_ProjectionType == ProjectionType.Gnomic)
            {
                txt_W = 8192;
                txt_H = 889;
                x_FOV = 1.5f;
                y_FOV = 0.2f;
                y_Rotation = 5.13f;
                x_Rotation = 0.25f;
                m_HeightY = 7f;
                material.shader = m_ShaderList[1];
            }

            if (m_ProjectionType == ProjectionType.Cropped)
            {
                txt_W = 6750;
                txt_H = 1080;;
                y_Rotation = 4.8f;
                x_Rotation = 1f;
                y_Divide = 5.8f;
                x_Divide = 4f;
                m_HeightY = 0.5f;
                material.shader = m_ShaderList[0];
            }

            if (m_ProjectionType == ProjectionType.CroppedFOV)
            {
                txt_W = 8192;
                txt_H = 889;
                y_Rotation = 4.8f;
                x_Rotation = 0f;
                y_Divide = 5.8f;
                x_Divide = 2.666f;
                m_HeightY = 0.5f;
                material.shader = m_ShaderList[0];
            }

            if (m_ProjectionType == ProjectionType.Squeezed)
            {
                txt_W = 6750;
                txt_H = 1080;
                y_Rotation = 0.85f;
                x_Rotation = 1f;
                y_Divide = 3.5f;
                x_Divide = 4f;
                m_HeightY = 5f;
                material.shader = m_ShaderList[0];
            }
        }
        else
        {
            // Set Left & right
            if (m_ProjectionType == ProjectionType.Gnomic)
            {
                txt_W = 3510;
                txt_H = 1080;
                x_FOV = 0.9f;
                y_FOV = 0.3f;
                y_Rotation = 5.23f;
                x_Rotation = 0.25f;
                m_HeightY = 7f;
                material.shader = m_ShaderList[1];
            }

            if (m_ProjectionType == ProjectionType.Cropped)
            {
                txt_W = 6750;
                txt_H = 1080;
                y_Rotation = 4.8f;
                x_Rotation = 1f;
                y_Divide = 5.8f;
                x_Divide = 4f;
                m_HeightY = 0.5f;
                material.shader = m_ShaderList[0];
            }

            if (m_ProjectionType == ProjectionType.CroppedFOV)
            {
                txt_W = 3510;
                txt_H = 1080;
                y_Rotation = 4.8f;
                x_Rotation = 0f;
                y_Divide = 5.8f;
                x_Divide = 8f;
                m_HeightY = 0.5f;
                material.shader = m_ShaderList[0];
            }

            if (m_ProjectionType == ProjectionType.Squeezed)
            {
                txt_W = 6750;
                txt_H = 1080;
                y_Rotation = 0.85f;
                x_Rotation = 1f;
                y_Divide = 3.5f;
                x_Divide = 4f;
                m_HeightY = 5f;
                material.shader = m_ShaderList[0];
            }

        }

        CycleThroughOrientations(frameCount, m_HeightY);
    } 

    void CycleThroughOrientations(int frameCount, float m_HeightY)
    {
        m_CubeMapPrefab.transform.localPosition = new Vector3(m_CubeMapPrefab.transform.localPosition.x, m_HeightY, m_CubeMapPrefab.transform.localPosition.z);
        if (m_ProjectionType != ProjectionType.CroppedFOV)
        {
            material.SetFloat("_EquiRotation", x_Rotation * frameCount);
        } else
        {
            if(frameCount == 0 || frameCount == 2)
            {
                material.SetFloat("_EquiRotation", x_Rotation + frameCount);
            } else
            {
                material.SetFloat("_EquiRotation", frameCount + 0.5f);
            }
            
        }
        

        material.SetFloat("_EquiRotationY", y_Rotation);
        if (m_ProjectionType == ProjectionType.Gnomic)
        {
            material.SetFloat("_FOVScale_X", x_FOV);
            material.SetFloat("_FOVScale_Y", y_FOV);
        } else
        {
            material.SetFloat("_DivideY", y_Divide);
            material.SetFloat("_DivideX", x_Divide);
        }
        ExportTexture(frameCount);
    }

    private void ExportTexture(int frameCount)
    {
        

        RenderTexture buffer = new RenderTexture(
                            txt_W,
                            txt_H,
                            0,                            // No depth/stencil buffer
                            RenderTextureFormat.ARGB32,   // Standard colour format

                            RenderTextureReadWrite.sRGB // No sRGB conversions
                        );

        texture = new Texture2D(txt_W, txt_H);
        Graphics.Blit(null, buffer, material);
        RenderTexture.active = buffer;           // If not using a scene camera

        texture.ReadPixels(
            new Rect(0, 0, txt_W, txt_H), // Capture the whole texture
            0, 0,                          // Write starting at the top-left texel
            false);                          // No mipmaps

        // Create a timestamped folder in the /SampleRecordings directory
        var recordingsDir = Path.Combine(Application.dataPath, "..", outputDirectory, m_Timestamp);

        // Create the direction-specific folder if it doesn't exist
        var directionFolder = "";
        switch (frameCount)
        {
            case 0:
                directionFolder = "SideB";
                break;
            case 1:
                directionFolder = "SideA";
                break;
            case 2:
                directionFolder = "SideD";
                break;
            case 3:
                directionFolder = "SideC";
                break;
        }

        var fullDirectionPath = Path.Combine(recordingsDir, directionFolder);
 
        if (!Directory.Exists(fullDirectionPath))
        {
            Directory.CreateDirectory(fullDirectionPath);
        }

        // Save the PNG file with a frame-specific name
        var filePath = Path.Combine(fullDirectionPath, $"{directionFolder}_{frame:D4}.png");
        System.IO.File.WriteAllBytes(filePath, texture.EncodeToPNG());

        RenderTexture.active = null;
        RenderTexture.Destroy(texture);
        buffer.Release();
    }

    private void SetupMatShaders()
    {
        ///material = this.GetComponent<RawImage>().material;
        m_ShaderList.Add(Shader.Find("Conversion/CubemapToEquirectangularSqueeze"));
        m_ShaderList.Add(Shader.Find("Conversion/CubemapToEquirectangularGnomic"));
        material.shader = m_ShaderList[1];
    }

    private void SetupFrameRateConfiguration()
    {
        frame = 0;
        m_CubeMapPrefab = GameObject.Find("360 Projection Center");
        Application.targetFrameRate = m_CaptureFrameRate;
        QualitySettings.vSyncCount = 0;
        Time.captureDeltaTime = 1.0f / m_CaptureFrameRate;
    }

    private void ToggleRecording()
    {
        if (Input.GetKeyUp(KeyCode.R))
        {
            m_Timestamp = DateTime.Now.ToString("yyyyMMddHHmmss");
            m_Record = true;
        }

        if (Input.GetKeyUp(KeyCode.S))
        {
            m_Record = false;
        }
    }
}