using PSO2SERVER.Database;
using PSO2SERVER.Models;
using PSO2SERVER.Object;
using PSO2SERVER.Protocol.Packets;
using PSO2SERVER.Zone;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PSO2SERVER.Protocol.Handlers
{
    [PacketHandlerAttr(0x04, 0x14)]
    public class ObjectInteract : PacketHandler
    {
        public class InteractPacket
        {
            // Fields
            public byte[] Unk1 { get; set; } // [u8; 0xC]
            public ObjectHeader Object1 { get; set; }
            public byte[] Unk2 { get; set; } // [u8; 0x4]
            public ObjectHeader Object3 { get; set; }
            public byte[] Object4 { get; set; } // [u8; 0x10]
            public string Action { get; set; }  // AsciiString

            // Constructor
            public InteractPacket()
            {
                Unk1 = new byte[0x0C]; // Initialize arrays with appropriate sizes
                Unk2 = new byte[0x04];
                Object4 = new byte[0x10];
                Action = string.Empty;
            }

            // Deserialize constructor (for example purposes, if needed)
            public InteractPacket(byte[] unk1, ObjectHeader object1, byte[] unk2, ObjectHeader object3, byte[] object4, string action)
            {
                Unk1 = unk1;
                Object1 = object1;
                Unk2 = unk2;
                Object3 = object3;
                Object4 = object4;
                Action = action;
            }
        }

        public override void HandlePacket(Client context, byte flags, byte[] data, uint position, uint size)
        {
            var reader = new PacketReader(data, position, size);
            var pkt = new InteractPacket
            {
                Unk1 = reader.ReadBytes(0x0C),
                Object1 = reader.ReadObjectHeader(),
                Unk2 = reader.ReadBytes(4), 
                Object3 = reader.ReadObjectHeader(),
                Object4 = reader.ReadBytes(0x10),
                Action = reader.ReadAscii(0xD711, 0xCA)
            };


            //Logger.Write($"PKT:Object1 {pkt.Object1.ToString()} Object3 {pkt.Object3.ToString()} Action {pkt.Action}");



            PSOObject srcObj;
            if(pkt.Object1.ObjectType == ObjectType.Object)
            {
                srcObj = ObjectManager.Instance.getObjectByID(context.CurrentMap.Name, pkt.Object1.ID);
            }
            else if(pkt.Object1.ObjectType == ObjectType.Player)
            {
                srcObj = new PSOObject
                {
                    Header = pkt.Object1,
                    Name = "Accounts"
                };
            }
            else
            {
                srcObj = null;
            }

            //Logger.WriteInternal("[OBJ] {0} (ID {1}) <{2}> --> Ent {3} (ID {4})", srcObj.name, srcObj.player.ID, command, (ObjectType)dstObject.ObjectType, dstObject.ID);

            // TODO: Delete this code and do this COMPLETELY correctly!!!
            if (pkt.Action == "Transfer" && context.CurrentMap.Name == "lobby")
            {
                // Try and get the teleport definition for the object...
                using (var db = new ServerEf())
                {
                    db.Configuration.AutoDetectChangesEnabled = true;
                    var teleporterEndpoint = db.Teleports.Find("lobby", (int)pkt.Object1.ID);

                    if (teleporterEndpoint == null)
                    {
                        Logger.WriteError("[OBJ] 传输 {0} 于 {1} 没有包含一个有效目的地!", srcObj.Header.ID, "lobby");
                        // Teleport Accounts to default point
                        context.SendPacket(new TeleportTransferPacket(srcObj, new PSOLocation(0f, 1f, 0f, -0.000031f, -0.417969f, 0.000031f, 134.375f)));
                        // Unhide player
                        context.SendPacket(new ObjectActionPacket(pkt.Object3, pkt.Object1, new ObjectHeader(), new ObjectHeader(), "Forwarded"));
                    }
                    else
                    {
                        PSOLocation endpointLocation = new PSOLocation()
                        {
                            RotX = teleporterEndpoint.RotX,
                            RotY = teleporterEndpoint.RotY,
                            RotZ = teleporterEndpoint.RotZ,
                            RotW = teleporterEndpoint.RotW,
                            PosX = teleporterEndpoint.PosX,
                            PosY = teleporterEndpoint.PosY,
                            PosZ = teleporterEndpoint.PosZ,
                        };
                        // Teleport Accounts
                        context.SendPacket(new TeleportTransferPacket(srcObj, endpointLocation));
                        // Unhide player
                        context.SendPacket(new ObjectActionPacket(pkt.Object3, pkt.Object1, new ObjectHeader(), new ObjectHeader(), "Forwarded")); 
                    }
                }
            }

            if (pkt.Action == "READY")
            {
                context.SendPacket(new ObjectActionPacket(new ObjectHeader((uint)context._account.AccountId, ObjectType.Player), srcObj.Header, srcObj.Header,
                    new ObjectHeader(), "FavsNeutral"));
                context.SendPacket(new ObjectActionPacket(new ObjectHeader((uint)context._account.AccountId, ObjectType.Player), srcObj.Header, srcObj.Header,
                    new ObjectHeader(), "AP")); // Short for Appear, Thanks Zapero!
            }

            if (pkt.Action == "Sit")
            {
                foreach (var client in Server.Instance.Clients)
                {
                    if (client.Character == null || client == context)
                        continue;

                    client.SendPacket(new ObjectActionPacket(new ObjectHeader((uint)client._account.AccountId, ObjectType.Player), srcObj.Header,
                        new ObjectHeader(pkt.Object3.ID, ObjectType.Player), new ObjectHeader(), "SitSuccess"));
                }
            }
        }
    }

}
