using System;
using Barotrauma.Networking;
using FarseerPhysics;
using Microsoft.Xna.Framework;

namespace Barotrauma
{
    partial class Level : Entity, IServerSerializable
    {
        public interface IEventData : NetEntityEvent.IData
        {
            public EventType EventType { get; }
        }

        public readonly struct SingleLevelWallEventData : IEventData
        {
            public EventType EventType => EventType.SingleDestructibleWall;
            public readonly DestructibleLevelWall Wall;
            
            public SingleLevelWallEventData(DestructibleLevelWall wall)
            {
                Wall = wall;
            }
        }

        public readonly struct GlobalLevelWallEventData : IEventData
        {
            public EventType EventType => EventType.GlobalDestructibleWall;
        }
        
        public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null)
        {
            if (!(extraData is IEventData eventData)) { throw new Exception($"Malformed level event: expected {nameof(Level)}.{nameof(IEventData)}"); }

            msg.WriteByte((byte)eventData.EventType);
            switch (eventData)
            {
                case SingleLevelWallEventData { Wall: var destructibleWall }:
                    int index = ExtraWalls.IndexOf(destructibleWall);
                    msg.WriteUInt16((ushort)(index == -1 ? ushort.MaxValue : index));
                    //write health using one byte
                    msg.WriteByte((byte)MathHelper.Clamp((int)(MathUtils.InverseLerp(0.0f, destructibleWall.MaxHealth, destructibleWall.Damage) * 255.0f), 0, 255));
                    break;
                case GlobalLevelWallEventData _:
                    foreach (LevelWall levelWall in ExtraWalls)
                    {
                        if (levelWall.Body.BodyType == BodyType.Static) { continue; }
                        msg.WriteSingle(levelWall.Body.Position.X);
                        msg.WriteSingle(levelWall.Body.Position.Y);
                        msg.WriteRangedSingle(levelWall.MoveState, 0.0f, MathHelper.TwoPi, 16);                    
                    }
                    break;
                default:
                    throw new Exception($"Malformed level event: did not expect {eventData.GetType().Name}");
            }
        }
    }
}
