﻿using System;
using System.Collections.Generic;
using System.Linq;
using DarkRift.Client.Unity;
using UnityEngine;
using MessageReceivedEventArgs = DarkRift.Client.MessageReceivedEventArgs;

namespace Dissonance.Integrations.DarkRift2.Demo
{
    // ReSharper disable once InconsistentNaming
    public class DR2RemotePlayerManager
        : MonoBehaviour
    {
        public GameObject RemotePlayerPrefab;

        private void OnEnable()
        {
            var client = FindObjectOfType<UnityClient>();
            client.MessageReceived += MessageReceived;
        }

        private void MessageReceived(object _, [NotNull] MessageReceivedEventArgs e)
        {
            using (var message = e.GetMessage())
            {
                if (message.Tag == Tags.PositionUpdateTag)
                {
                    using (var reader = message.GetReader())
                    {
                        var sender = reader.ReadUInt16();
                        var dissonanceName = reader.ReadString();
                        var avatar = GetOrCreateAvatar(sender, dissonanceName);
                        avatar.TargetPosition = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
                        avatar.TargetRotation = Quaternion.AngleAxis(reader.ReadSingle(), Vector3.up);
                    }
                }
                else if (message.Tag == Tags.DeleteRemotePlayer)
                {
                    using (var reader = message.GetReader())
                    {
                        var sender = reader.ReadUInt16();
                        var avatar = TryGetAvatar(sender);
                        if (avatar)
                            Destroy(avatar.gameObject);
                        else
                            Debug.LogWarning(string.Format("Server informed us client {0} leaving, but no such client exists locally", sender));
                    }
                }
            }
        }

        [CanBeNull] private DR2RemotePlayer TryGetAvatar(ushort sender)
        {
            return GetComponentsInChildren<DR2RemotePlayer>().FirstOrDefault(a => a.ID == sender);
        }

        [NotNull] private DR2RemotePlayer GetOrCreateAvatar(ushort sender, string dissonanceName)
        {
            var avatar = TryGetAvatar(sender);
            if (!avatar)
            {
                var obj = Instantiate(RemotePlayerPrefab, transform);
                obj.name = string.Format("Avatar for '{0}'", dissonanceName);
                avatar = obj.GetComponent<DR2RemotePlayer>();
                avatar.ID = sender;
            }

            var dPlayer = avatar.GetComponent<DarkRift2Player>();
            if (!dPlayer.IsTracking || dPlayer.PlayerId != dissonanceName)
                dPlayer.SetPlayerId(NetworkPlayerType.Remote, dissonanceName);

            return avatar;
        }
    }
}
