using System.Collections.Generic;
using Unity.WebRTC;
using UnityEngine;
using Unity.Plastic.Newtonsoft.Json;

namespace DesktopVision.DVWebRTC {
/// <summary>
/// This class is used to store a Meetings session for use with Desktop Vision
/// </summary>
class MeetingsDevSessionDescription
{
	/// <summary>
	/// The session type
	/// </summary>
	public string type;
	/// <summary>
	/// The Session Description Protocol
	/// https://en.wikipedia.org/wiki/Session_Description_Protocol
	/// </summary>
	public string sdp;
	/// <summary>
	/// Session Description
	/// </summary>
	/// <param name="desc">The session description which includes the SDP</param>
	/// <param name="type">Type of RTC Session</param>
	public MeetingsDevSessionDescription(RTCSessionDescription desc, string type)
	{
		this.type = type;
		this.sdp = desc.sdp;
	}
}

/// <summary>
/// This class is used to store a webrtc Candidate for use with Desktop Vision
/// </summary>
class DVCandidate
{
	/// <summary>
	/// Always "candidate"
	/// </summary>
	public string type;
	public MeetingCandidate candidate;
	/// <summary>
	/// 
	/// </summary>
	/// <param name="ice">The RTC Ice candidate</param>
	public DVCandidate(RTCIceCandidate ice)
	{
		this.candidate = new MeetingCandidate(ice.Candidate, ice.SdpMid, ice.SdpMLineIndex ?? 0);
		this.type = "candidate";
	}
}
class DVTransceiverRequestSignal
{

	/// <summary>
	/// The transciever type
	/// </summary>
	public string type;

	/// <summary>
	/// The transceiver request
	/// </summary>
	public DVTransceiverRequest transceiverRequest;
	/// <summary>
	/// The transceiver request signal
	/// </summary
	/// <param name="transceiverRequest">The transceiver request</param>
	/// <param name="type">The transceiver type</param>
	public DVTransceiverRequestSignal(string type, DVTransceiverRequest transceiverRequest)
	{
		Debug.Log(transceiverRequest);
		this.type = type;
		this.transceiverRequest = transceiverRequest;
	}
}
class DVTransceiverRequest
{
	/// <summary>
	/// The transceiver request kind
	/// </summary>
	public string kind;
	/// <summary>
	/// The transceiver request 
	/// </summary>
	/// <param name="kind">The transceiver request kind</param>
	public DVTransceiverRequest(string kind)
	{
		this.kind = kind;
	}
}

/// <summary>
/// This class is used to store a webrtc Candidate for use with Desktop Vision
/// </summary>

class MeetingCandidate
{
	/// <summary>
	/// The candidate
	/// </summary>
	public string candidate;
	/// <summary>
	/// The sdpMid
	/// </summary>
	public string sdpMid;
	/// <summary>
	/// The sdpMLineIndex
	/// </summary>
	public int sdpMLineIndex;
	/// <summary>
	/// The candidate
	/// </summary>
	/// <param name="candidate">The candidate</param>
	/// <param name="sdpMid">The sdpMid</param>
	/// <param name="sdpMLineIndex">The sdpMLineIndex</param>
	public MeetingCandidate(string Candidate, string SdpMid, int SdpMLineIndex = 0)
	{
		this.candidate = Candidate;
		this.sdpMid = SdpMid;
		this.sdpMLineIndex = SdpMLineIndex;
	}
}

/// <summary>
/// This class is used to store a signaling payload
/// </summary>
class DVPayload
{
	/// <summary>
	/// The payload body
	/// </summary>
	public string body;
	/// <summary>
	/// The payload
	/// </summary>
	/// <param name="body">The payload body</param>
	public DVPayload(string body)
	{
		this.body = body;
	}
}

/// <summary>
/// This class is used to format and store a signal
/// </summary>
public class SignalingMessage
{
	/// <summary>
	/// The signal from
	/// </summary>
	public string from;
	/// <summary>
	/// The signals
	/// </summary>
	public string[] signals;
	/// <summary>
	/// The signal to
	/// </summary>
	public string[] to;
	/// <summary>
	/// The signal created at timestamp
	/// </summary>
	public double createdAt;

	/// <summary>
	/// The signal
	/// </summary>
	/// <param name="from">The signal from</param>
	/// <param name="to">The signal to</param>
	/// <param name="signals">The signals</param>
	/// <param name="createdAt">The signal created at timestamp</param>
	public SignalingMessage(string[] to, string from, string[] signals, double createdAt)
	{
		this.to = to;
		this.from = from;
		this.createdAt = createdAt;
		this.signals = signals;
	}
}

/// <summary>
/// This class is used to store a Signal
/// </summary>
public class SDPSignal
{

	/// <summary>
	/// The signal type
	/// </summary>
	public string type;
	/// <summary>
	/// The signal sdp
	/// </summary>
	public string sdp;

	/// <summary>
	/// The signal
	/// </summary>
	/// <param name="type">The signal type</param>
	/// <param name="sdp">The signal sdp</param>
	public SDPSignal(string type, string sdp)
	{
		this.type = type;
		this.sdp = sdp;
	}
}
	/// <summary>
	/// This class is used to store a Candiate Signal
	/// </summary>
	public class CandidateSignal
	{
		/// <summary>
		/// The candidate signal type
		/// </summary>
		public string type;
		/// <summary>
		/// The candidate signal candidate
		/// </summary>
		public RTCIceCandidateInit candidate;
		/// <summary>
		/// The candidate signal
		/// </summary>
		/// <param name="type">The candidate signal type</param>
		/// <param name="candidate">The candidate signal candidate</param>
		public CandidateSignal(string type, object candidate)
		{
			this.type = type;
			this.candidate = JsonUtility.FromJson<RTCIceCandidateInit>(JsonUtility.ToJson(candidate));
		}
	}
	

	/// <summary>
	/// The Desktop Vision Formatted Ice Candidate
	/// </summary>
	public class IceCandidate
{
	/// <summary>
	/// The sdp mid
	/// </summary>
	public string sdpMid;
	/// <summary>
	/// The ice candidate
	/// </summary>
	public string candidate;
	/// <summary>
	/// The sdp mline index
	/// </summary>
	public int sdpMLineIndex;

	/// <summary>
	/// The Desktop Vision Formatted Ice Candidate
	/// </summary>
	/// <param name="sdpMid">The sdp mid</param>
	/// <param name="candidate">The ice candidate</param>
	/// <param name="sdpMLineIndex">The sdp mline index</param>
	public IceCandidate(string candidate, string sdpMid, int sdpMLineIndex)
	{
		this.candidate = candidate;
		this.sdpMid = sdpMid;
		this.sdpMLineIndex = sdpMLineIndex;
	}
}

/// <summary>
/// This class is used to store a Desktop Vision Formatted Message
/// </summary>
public class RoomMessage
{
	/// <summary>
	/// The message type
	/// </summary>
	string type;
	/// <summary>
	/// The message body
	/// </summary>
	string message;
	/// <summary>
	/// The room message
	/// </summary>
	/// <param name="type">The message type</param>
	/// <param name="message">The message body</param>
	public RoomMessage(string type, string message)
	{
		this.type = type;
		this.message = message;
	}
}

/// <summary>
/// This class is used to store Desktop Vision Room Options required to connect to a computer.
/// </summary>
public class RoomOptions
{
	/// <summary>
	/// The auth token
	/// </summary>
	public string auth_token;
	/// <summary>
	/// The user id
	/// </summary>
	public string uid;
	/// <summary>
	/// room info
	/// </summary>
	public string info;
	/// <summary>
	/// The project ID
	/// </summary>
	public int project_id;
	/// <summary>
	/// The room ID
	/// </summary>
	public int room_id;
	/// <summary>
	/// The room ice servers
	/// </summary>
	public RTCIceServer[] ice_servers;


	/// <summary>
	/// The room options
	/// </summary>
	/// <param name="auth_token">The auth token</param>
	/// <param name="uid">The user id</param>
	/// <param name="info">room info</param>
	/// <param name="project_id">The project ID</param>
	/// <param name="room_id">The room ID</param>
	/// <param name="ice_servers">The room ice servers</param>
	public RoomOptions(List<MeetingIce> ice_servers, string auth_token = "", int room_id = 0, int project_id = 0, string uid = "", string info = "")
	{
		List<RTCIceServer> servers = new List<RTCIceServer>();
		foreach (MeetingIce ice in ice_servers)
		{
			RTCIceServer ice_server = new RTCIceServer();
			ice_server.credential = ice.credential;
			ice_server.urls = new[] { ice.urls };
			ice_server.username = ice.username;
			ice_server.credentialType = RTCIceCredentialType.Password;

			servers.Add(ice_server);
		}
		this.ice_servers = servers.ToArray();
		this.auth_token = auth_token;
		this.room_id = room_id;
		this.project_id = project_id;
		this.uid = uid;
		this.info = info;
	}
}


/// <summary>
/// Room options wrapper used to handle deserializing room options
/// </summary>
public class RoomOptionsContainer
{
	/// <summary>
	/// The room options
	/// </summary>
	public RoomOptions roomOptions;
	/// <summary>
	/// The room options wrapper
	/// </summary>
	/// <param name="roomOptions">The room options</param>
	public RoomOptionsContainer(RoomOptions roomOptions)
	{
		this.roomOptions = roomOptions;
	}
}
/// <summary>
/// ICE connection formated for Desktop Vision
/// </summary>
public class MeetingIce
{
	/// <summary>
	///  The credential
	/// </summary>
	public string credential;
	/// <summary>
	/// The username
	/// </summary>
	public string username;
	/// <summary>
	/// The url
	/// </summary>
	public string url;
	/// <summary>
	/// The urls
	/// </summary>
	public string urls;

	/// <summary>
	/// ICE connection formated for Desktop Vision
	/// </summary>
	public MeetingIce(string urls, string credential = "", string username = "", string url = "")
	{
		this.credential = credential;
		this.username = username;
		this.urls = urls;
		this.url = url;
	}
}
}