using UnityEngine;
using System.Collections;

using com.spacepuppy.Tween;
using UnityEngine.VR.WSA.Input;
using UnityEngine.VR.WSA.Persistence;

using HoloToolkit.Unity.InputModule;
using System;
using HoloToolkit.Unity;
using System.Collections.Generic;
#if NETFX_CORE
using Windows.ApplicationModel;
using Windows.ApplicationModel.DataTransfer;
using Windows.Storage.Streams;
#endif

public class PhotoAppCapture : Singleton<PhotoAppCapture>, IInputClickHandler
{
    // Replace "UnityEngine.VR..." with "UnityEngine.XR..." in future versions
    // Do not use Unity 2017.2 because some HoloLens interactions are broken in
    // Unity 2017.2 version which will be fixed in future versions of Unity
    UnityEngine.VR.WSA.WebCam.PhotoCapture photoCaptureObject = null;
    [SerializeField]
    private GameObject prefabTargetForTexture;
    private GameObject targetObjectForTexture;
    private Texture2D targetTexture = null;

    [Tooltip("Audio clip to play when interacting with this hologram.")]
    [SerializeField]
    private AudioClip TargetFeedbackSound;
    private AudioSource audioSource;
    private GameObject audioGameObject;

    [SerializeField]
    private bool saveFileOnCapture = true;
    [SerializeField]
    private bool captureHolograms = false;

    // Use this for initialization
    void Start()
    {
        RegisterManagers();
    }

    public GameObject GetPolaroidPrefab()
    {
        return prefabTargetForTexture;
    }

    void RegisterManagers()
    {
        InputManager.Instance.AddGlobalListener(gameObject);
    }


    bool isAnimating = false;
    bool isCapturing = false;
    public float animationSpeed = 3f;
    float timePos;
    float test;
    private bool uploadToTwitter = false;
    void Update()
    {

        if (Input.GetMouseButtonDown(0) && !isAnimating && !isCapturing && !GazeManager.Instance.HitObject)
        {
            CapturePhoto(false);
        }

        if (Input.GetMouseButtonDown(1) && !isAnimating)
        {
            CapturePhoto(true);
        }

        if (isAnimating)
        {
            animatePolaroidPosition();
        }

    }

    void animatePolaroidPosition()
    {
        // animate the polaroids position from the camera to the position where the image will be placed
        timePos += animationSpeed * Time.deltaTime;
        targetObjectForTexture.transform.position = com.spacepuppy.Tween.EaseMethods.EaseVector3(EaseMethods.SineEaseIn, targetObjectForTexture.transform.position, targetPoint, timePos, 3);

        targetObjectForTexture.transform.LookAt(mainCam.transform, Vector3.up);
        if (Vector3.Distance(targetObjectForTexture.transform.position, targetPoint) < 0.015)
        {
            targetObjectForTexture.transform.parent = null;
            
            isAnimating = false;
            targetObjectForTexture.AddComponent<UnityEngine.VR.WSA.WorldAnchor>();
            
            timePos = 0;
        }
    }

    public void CapturePhoto()
    {
        CapturePhoto(captureHolograms);
    }

    public void CapturePhoto(bool captureHolograms)
    {
        isCapturing = true;

        Resolution resolution = new Resolution();

        // choose the highest capture resolution
        foreach (Resolution en in UnityEngine.VR.WSA.WebCam.PhotoCapture.SupportedResolutions)
        {
            if (en.height > resolution.height)
            {
                resolution = en;
            }
        }

        Resolution cameraResolution = resolution;
        targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);

        // Create a PhotoCapture object
        UnityEngine.VR.WSA.WebCam.PhotoCapture.CreateAsync(captureHolograms, delegate (UnityEngine.VR.WSA.WebCam.PhotoCapture captureObject) {

                photoCaptureObject = captureObject;
                UnityEngine.VR.WSA.WebCam.CameraParameters cameraParameters = new UnityEngine.VR.WSA.WebCam.CameraParameters();

                // decide if "holograms" should be captured or not
                if (captureHolograms == false)
                {
                    cameraParameters.hologramOpacity = 0.0f;
                }else
                {
                    cameraParameters.hologramOpacity = 1.0f;
                }

                // set the new camera parameters
                cameraParameters.cameraResolutionWidth = cameraResolution.width;
                cameraParameters.cameraResolutionHeight = cameraResolution.height;
                cameraParameters.pixelFormat = UnityEngine.VR.WSA.WebCam.CapturePixelFormat.BGRA32;

                // Activate the camera
                photoCaptureObject.StartPhotoModeAsync(cameraParameters, delegate (UnityEngine.VR.WSA.WebCam.PhotoCapture.PhotoCaptureResult result) {
                // Take a picture async
                photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
                });
        });

        // play Audioclip.
        if (TargetFeedbackSound != null)
        {
            audioSource = Camera.main.GetComponent<AudioSource>();

            audioSource.clip = TargetFeedbackSound;
            audioSource.playOnAwake = false;
            audioSource.spatialBlend = 1;
            audioSource.dopplerLevel = 0;

            audioSource.Play();
        }
    }

    public Camera mainCam;
    Vector3 targetPoint;
    static ArrayList textureList = new ArrayList();
    void OnCapturedPhotoToMemory(UnityEngine.VR.WSA.WebCam.PhotoCapture.PhotoCaptureResult result, UnityEngine.VR.WSA.WebCam.PhotoCaptureFrame photoCaptureFrame)
    {

        // Copy the raw image data into the target texture
        photoCaptureFrame.UploadImageDataToTexture(targetTexture);

        uploadToTwitter = false;
        if (uploadToTwitter == false)
        {
            // Create a GameObject to which the texture can be applied
            targetObjectForTexture = Instantiate(prefabTargetForTexture);
            Renderer texRenderer = targetObjectForTexture.GetComponent<Renderer>() as Renderer;

            // Set a unique name for the polaroid object
            targetObjectForTexture.name = "iXPhotoApp_" + targetTexture.GetHashCode() + UnityEngine.Random.Range(123400, int.MaxValue).ToString() + UnityEngine.Random.Range(123400, int.MaxValue).ToString();
            targetObjectForTexture.transform.position = mainCam.transform.position;
            targetObjectForTexture.transform.parent = mainCam.transform;

            // Apply the new photo to the polaroid
            textureList.Add(targetTexture);
            texRenderer.material.SetTexture("_MainTex", targetTexture);

            // Save the new polaroid to disk
            if (saveFileOnCapture)
            {
                KeyValuePair<string, Texture2D> newPolaroid = new KeyValuePair<string, Texture2D>(targetObjectForTexture.name, targetTexture);
                PersistenceManager.Instance.SavePolaroidFile(newPolaroid);
                PersistenceManager.Instance.SaveWorldAnchor(newPolaroid);
            }

            // start the fade in animation for the polaroid object
            float distance = 2f;
            targetPoint = new Vector3(mainCam.transform.position.x + (mainCam.transform.forward.normalized.x * distance), mainCam.transform.position.y + (mainCam.transform.forward.normalized.y * distance), mainCam.transform.position.z + (mainCam.transform.forward.normalized.z * distance));
            isAnimating = true;

            // Deactivate the camera
            photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
        }
    }

    void OnStoppedPhotoMode(UnityEngine.VR.WSA.WebCam.PhotoCapture.PhotoCaptureResult result)
    {
        // set the capturing state back to false
        isCapturing = false;
        // Shutdown the photo capture resource
        photoCaptureObject.Dispose();
        photoCaptureObject = null;
    }

    public void OnInputClicked(InputClickedEventData eventData)
    {
        // if no object is focused create a new photo
        if (!GazeManager.Instance.HitObject && !isAnimating && !isCapturing)
        {
            CapturePhoto(captureHolograms);
        }
    }
}