using System.Linq;
using UnityEngine;
using UnityEngine.UI;

public class CameraManager : MonoBehaviour
{
    public WebCamDevice wDevice;
    public Button freezeButton;
    public Button resumeButton;
    public RawImage photoBox;
    private Texture2D photo;
    private int numberOfWebcams;
    private WebCamTexture wTexture;

    // Start is called before the first frame update
    void OnEnable()
    {
        WebcamResume();
    }

    void OnDisable()
    {
        wTexture = null;
    }

    void Start()
    {
        wDevice = WebCamTexture.devices.FirstOrDefault(x => x.isFrontFacing == false);
        numberOfWebcams = WebCamTexture.devices.Count();
    }

    // Update is called once per frame
    void Update()
    {
        Texture2D texture = GetPhoto();

        if (texture)
        {
            photoBox.texture = texture;
        }

        Resources.UnloadUnusedAssets();
    }

    public void WebcamResume()
    {
        if (wTexture == null)
            wTexture = new WebCamTexture(wDevice.name);

        wTexture.Play();
        photo = null;
        photoBox.texture = null;
        freezeButton.gameObject.SetActive(true);
        resumeButton.gameObject.SetActive(false);
    }

    public void WebcamChange()
    {
        foreach (WebCamDevice loopDevice in WebCamTexture.devices)
        {
            if ((wDevice.isFrontFacing && !loopDevice.isFrontFacing) || (!wDevice.isFrontFacing && loopDevice.isFrontFacing))
            {
                wDevice = loopDevice;
                wTexture = new WebCamTexture(wDevice.name);
                WebcamResume();
                break;
            }
        }
    }

    public void WebcamStop()
    {
        photo = GetPhoto();
        wTexture.Stop();
        freezeButton.gameObject.SetActive(false);
        resumeButton.gameObject.SetActive(true);
    }

    Texture2D RotateTexture(Texture2D originalTexture, bool clockwise)
    {
        Color32[] original = originalTexture.GetPixels32();
        Color32[] rotated = new Color32[original.Length];
        int w = originalTexture.width;
        int h = originalTexture.height;

        int iRotated, iOriginal;

        for (int j = 0; j < h; ++j)
        {
            for (int i = 0; i < w; ++i)
            {
                iRotated = (i + 1) * h - j - 1;
                iOriginal = clockwise ? original.Length - 1 - (j * w + i) : j * w + i;
                rotated[iRotated] = original[iOriginal];
            }
        }

        Texture2D rotatedTexture = new(h, w);
        rotatedTexture.SetPixels32(rotated);

        return rotatedTexture;
    }

    Texture2D CropTexture(WebCamTexture originalTexture)
    {
        var x = 0;
        var y = 0;
        var size = originalTexture.height;

        if (originalTexture.height > originalTexture.width)
        {
            size = originalTexture.width;
            y = (originalTexture.height - originalTexture.width) / 2;
        }
        else if (originalTexture.height < originalTexture.width)
        {
            size = originalTexture.height;
            x = (originalTexture.width - originalTexture.height) / 2;
        }

        Texture2D croppedTexture = new(size, size);
        croppedTexture.SetPixels(originalTexture.GetPixels(x, y, size, size));

        return croppedTexture;
    }

    public Texture2D GetPhoto()
    {
        if (photo)
        {
            return photo;
        }

        if (!wTexture || numberOfWebcams < 1)
        {
            return null;
        }

        Texture2D cropped = CropTexture(wTexture);
        Texture2D rotated = RotateTexture(cropped, !wDevice.isFrontFacing);
        rotated.Apply();

        return rotated;
    }
}
