﻿using System;
using System.Collections.Generic;
using System.IO;
using GameLib.Networking;

namespace JumpAndRun.Networking.Packages
{
    public class TimeFactorPackage : IPackage
    {
        private readonly TimeInfo _timeInfo;

        public string PackageName => "JumpAndRun.Packages.TimeFactor";

        public TimeFactorPackage() { }

        public TimeFactorPackage(float environmentFactor, Dictionary<Guid, float> playerTimeFactor)
        {
            _timeInfo = new TimeInfo(environmentFactor, playerTimeFactor);
        }

        public byte[] Encode()
        {
            var stream = new NetworkStream(new MemoryStream());

            stream.WriteInt(ContentManager.Instance.NetworkId[PackageName]);

            stream.WriteFloat(_timeInfo.EnvironmentTimeFactor);
            if(_timeInfo.PlayerTimeFactor == null)
            {
                stream.WriteInt(0);
            }
            else
            {
                stream.WriteInt(_timeInfo.PlayerTimeFactor.Count);
                foreach (var item in _timeInfo.PlayerTimeFactor)
                {
                    stream.WriteByteArray(item.Key.ToByteArray(), 16);
                    stream.WriteFloat(item.Value);
                }
            }

            var data = stream.GetBytes();
            stream.BaseStream.Dispose();

            return data;
        }

        public void Execute(NetworkStream baseStream, ClientPackageInfo info)
        {
            var environment = baseStream.ReadFloat();
            var playerFactor = GetInfo(baseStream);
            TimeManager.Instance.PackageFlip();
            TimeManager.Instance.EnvironmentTimeFactor = environment;
            if (playerFactor != null)
                TimeManager.Instance.PlayerTimeFactor = playerFactor;
            TimeManager.Instance.PackageFlip();
        }

        public string ExecuteDebug(NetworkStream baseStream)
        {
            var environment = baseStream.ReadFloat();
            GetInfo(baseStream);

            return PackageName + " Environment: " + environment;
        } 

        private static Dictionary<Guid, float> GetInfo(NetworkStream baseStream)
        {
            var length = baseStream.ReadInt();
            if (length == 0) return null;
            var playerFactor = new Dictionary<Guid, float>();
            for (var i = 0; i < length; i++)
            {
                playerFactor.Add(new Guid(baseStream.ReadByteArray(16)), baseStream.ReadFloat());
            }
            return playerFactor;
        }

        public void ExecuteServer(NetworkStream baseStream, ServerPackageInfo info)
        {
            var environment = baseStream.ReadFloat();
            var playerFactor = GetInfo(baseStream);

            TimeManager.Instance.EnvironmentTimeFactor = environment;
            if (playerFactor != null)
                TimeManager.Instance.PlayerTimeFactor = playerFactor;
            info.SendToAllClients(new TimeFactorPackage(environment, playerFactor));
        }
    }
}
