#if UNITY_EDITOR_WIN || WINDOWS_UWP || UNITY_STANDALONE_WIN

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Windows.WebCam;
using UnityEngine.Windows;
using UnityEngine.Events;

namespace SimplifyXR
{

    public class WinPhotoCapture : MonoBehaviour, IPhotoCapture
    {
        public UnityEvent captureReadyEvent;
        public UnityEvent<Texture2D> photoCaptured;

        UnityEvent IPhotoCapture.captureReady => captureReadyEvent;
        UnityEvent<Texture2D> IPhotoCapture.photoCaptured  => photoCaptured;

        System.IO.DirectoryInfo cameraCaptureDir;
        private PhotoCapture photoCaptureObject = null;
        private Texture2D targetTexture = null;
        private CameraParameters camparams;
       
        private bool enableHolograms = false;
        private BasicResolutionOptions resolution = BasicResolutionOptions.highQuality;

        private bool captureAfterCreate = false;
  
        //First capture after plugging in webcam appears dark, only happens on per inital plug in (not per applicaion start)
        //Seems to affect pluggable cameras (not HL), in future may do a dry run capture on startup to flush...
        public void CreateCapture(bool immediateCapture)
        {
            captureAfterCreate = immediateCapture;
            //always set holograms to true, we change opacity in parameters 
            PhotoCapture.CreateAsync(true, OnPhotoCaptureCreated);
        }

        void OnPhotoCaptureCreated(PhotoCapture captureObject)
        {
            photoCaptureObject = captureObject;

            Resolution cameraResolution;
            var orderedRes = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height);

            switch (resolution)
            {
                case BasicResolutionOptions.highQuality:
                    cameraResolution = orderedRes.First();
                    break;
                case BasicResolutionOptions.mediumQuality:
                    int middleIndex = PhotoCapture.SupportedResolutions.Count() / 2;
                    cameraResolution = orderedRes.ToList()[middleIndex];
                    break;
                case BasicResolutionOptions.lowQuality:
                    cameraResolution = orderedRes.Last();
                    break;
                default:
                    cameraResolution = orderedRes.First();
                    break;
            }

            CameraParameters c = new CameraParameters();

            if (enableHolograms)
                c.hologramOpacity = 1.0f;
            else
                c.hologramOpacity = 0.0f;

            c.cameraResolutionWidth = cameraResolution.width;
            c.cameraResolutionHeight = cameraResolution.height;
            c.pixelFormat = CapturePixelFormat.BGRA32;

            camparams = c;
            captureObject.StartPhotoModeAsync(c, OnPhotoModeStarted);
        }

        private List<string> ConvertResolutionToString(List<Resolution> resOptions)
        {
            List<string> val = new List<string>();

            foreach (Resolution res in resOptions)
            {
                val.Add(res.ToString());
            }

            return val;
        }

        void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
        {
            photoCaptureObject.Dispose();
            photoCaptureObject = null;
        }

        private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
        {
            if (result.success)
            {
                if (captureAfterCreate)
                {
                    photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
                    captureAfterCreate = false;
                }
                else
                {
                    captureReadyEvent?.Invoke();
                }
            }
            else
            {
                Debug.LogError("Unable to start photo mode!");
            }
        }

        public void SetCameraOptions(BasicResolutionOptions res, bool enable)
        {
            resolution = res;
            enableHolograms = enable;
        }

        public List<Resolution> GetSupportedResolutions()
        {
            if (photoCaptureObject != null)
            {
                return PhotoCapture.SupportedResolutions.ToList();
            }
            else
                return null;
        }

        void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
        {
            if (result.success)
            {
                // Create our Texture2D for use and set the correct resolution
                targetTexture = new Texture2D(camparams.cameraResolutionWidth, camparams.cameraResolutionHeight);
                // Copy the raw image data into our target texture
                photoCaptureFrame.UploadImageDataToTexture(targetTexture);

                photoCaptured?.Invoke(targetTexture);
            }
            // Clean up
            photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
        }

        public void CapturePhoto()
        {
            if (photoCaptureObject != null)
            {
                photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
            }
        }

        private void OnDestroy()
        {
            // Clean up
            if (photoCaptureObject != null)
                photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
        }

        private void OnDisable()
        {
            // Clean up
            if (photoCaptureObject != null)
                photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
        }
    }
}

#endif