using System.Threading.Tasks;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Collections;
using System.Linq;
using System;
using UnityEngine;
using DesktopVision.DVAuth;
using DesktopVision.DVWebRTC;
using Unity.Plastic.Newtonsoft.Json;

namespace DesktopVision
{
    public class DVManagedComputer : MonoBehaviour
    {

        /// <summary>
        /// The size of the screen
        /// </summary>
        public float screenSize = 1.0f;
        public DVComputer computer;
        public DVConnectionManager connectionManager;
        private Auth dvAuth;
        /// <summary>
        /// The Desktop Vision APP ID used to generate oauth codes
        /// </summary>
        public string DesktopVisionAppId = "";
        /// <summary>
        /// The Desktop Vision API KEY used to generate oauth codes
        /// </summary>
        public string DesktopVisionApiKey = "";
        void Start()
        {
            computer.screenSize = screenSize;
            computer.setScreenSaver();
            computer.ManagementButtons.SetActive(true);
            dvAuth = new Auth();
            dvAuth.generateCode(DesktopVisionAppId, DesktopVisionApiKey);
            dvAuth.Dispatch += ListenAuthEvents;
            connectionManager.Dispatch += ListenConnectionEvents;

            computer.DVButton.onClick.RemoveAllListeners();
            computer.DVButton.onClick.AddListener(TriggerDVButton);

            computer.RefreshButton.onClick.RemoveAllListeners();
            computer.RefreshButton.onClick.AddListener(ResetComputer);
        }

        void ResetComputer()
        {
            computer.setScreenSaver();
            dvAuth.DesktopVisionAuthCode = null;
            try
            {
                connectionManager.endRTC();
            }
            catch (Exception e)
            {
                Debug.Log("WebRTC already disposed");
            }
        }

        void TriggerDVButton()
        {
            computer.setScreenSaver();
            computer.ManagementButtons.SetActive(true);
            dvAuth.generateCode(DesktopVisionAppId, DesktopVisionApiKey);
        }
        private void ListenConnectionEvents(object sender, ConnectionEventArgs connectionEvent)
        {
            if (connectionEvent.connectionError != null)
            {
                Debug.Log(connectionEvent.connectionError);
            }
            else if (connectionEvent.message == "stream-added")
            {
                computer.setVideo();
            }
        }
        async private void ListenAuthEvents(object sender, AuthEventArgs authEvent)
        {
            if (authEvent.authcode != null && authEvent.authcode.code != null)
            {
                Debug.Log(authEvent.authcode.code);
                computer.setText(authEvent.authcode.code, $"Enter the code {authEvent.authcode.code} at https://desktop.vision/app/#/authorize");
                await dvAuth.waitForAccessToken(DesktopVisionAppId, DesktopVisionApiKey, authEvent.authcode.code);
            }

            if (authEvent.authToken != null)
            {
                computer.setText("Authorized", "You will soon be connected to your computer, if a connection message does not occur shortly, please generate a new code by clicking the Desktop Vision icon in the bottom left corner.");
                GetComputer(authEvent.authToken.access_token, authEvent.authToken.uid, authEvent.authToken.computerId);
            }

            if (authEvent.authError != null)
            {
                Debug.Log(authEvent.authError);
            }
        }

        async private void GetComputer(string token, string uid, string computerId)
        {
            List<DVComputerRecord> computers = await dvAuth.listUserComputers(token, uid);

            RoomOptions options = await dvAuth.getUserComputerConnectionOptions(token, computerId);
            Debug.Log(options);

            connectionManager.StartConnection(options);
            computer.setText("Connected", "If the streamer app is running, you will soon be able to see and control your computer from here.");

            computer.DispatchCursor += ListenCursorEvents;
            computer.DispatchKeyboard += ListenKBEvents;
        }

        private void ListenKBEvents(object sender, DVKeyEvent e)
        {
            DVKeyboardPeerMessage controlEvent = new DVKeyboardPeerMessage(e.webrtc.localParticpant, e);
            string jsonMessage = JsonConvert.SerializeObject(controlEvent);
            e.webrtc.SendPeerMessage(jsonMessage);
        }
        private void ListenCursorEvents(object sender, DVCursorEvent e)
        {
            DVCursorPeerMessage controlEvent = new DVCursorPeerMessage(e.webrtc.localParticpant, e);
            string jsonMessage = JsonConvert.SerializeObject(controlEvent);
            e.webrtc.SendPeerMessage(jsonMessage);
        }
    }
}