using SharpChat.Messages;
using System.Text;

namespace SharpChat.SockChat.S2CPackets;

public class ContextMessageS2CPacket(Message msg, bool notify = false) : S2CPacket {
    public string Pack() {
        bool isAction = msg.Flags.HasFlag(MessageFlags.Action);
        bool isBroadcast = msg.Flags.HasFlag(MessageFlags.Broadcast);
        bool isPrivate = msg.Flags.HasFlag(MessageFlags.Private);

        StringBuilder sb = new();

        sb.Append("7\t1\t");
        sb.Append(msg.Created.ToUnixTimeSeconds());
        sb.Append('\t');

        switch(msg.Type) {
            case "msg:add":
            case "SharpChat.Events.ChatMessage":
                if(isBroadcast || msg.SenderId is null) {
                    sb.Append("-1\tChatBot\tinherit\t\t0\fsay\f");
                } else {
                    sb.Append(msg.SenderId);
                    sb.Append('\t');
                    sb.Append(msg.SenderLegacyName);
                    sb.Append('\t');
                    sb.Append(msg.SenderColour);
                    sb.Append('\t');
                    sb.Append(msg.SenderRank);
                    sb.Append(' ');
                    sb.Append(msg.SenderPermissions.HasFlag(UserPermissions.KickUser) ? '1' : '0');
                    sb.Append(' ');
                    sb.Append(msg.SenderPermissions.HasFlag(UserPermissions.ViewLogs) ? '1' : '0');
                    sb.Append(' ');
                    sb.Append(msg.SenderPermissions.HasFlag(UserPermissions.SetOwnNickname) ? '1' : '0');
                    sb.Append(' ');
                    sb.Append(msg.SenderPermissions.HasFlag(UserPermissions.CreateChannel) ? (msg.SenderPermissions.HasFlag(UserPermissions.SetChannelPermanent) ? '2' : '1') : '0');
                    sb.Append('\t');
                }

                if(isAction)
                    sb.Append("<i>");

                sb.Append(
                    (msg.Data.RootElement.GetProperty("text").GetString()?
                        .Replace("<", "&lt;")
                        .Replace(">", "&gt;")
                        .Replace("\n", " <br/> ")
                        .Replace("\t", "    ")) ?? string.Empty
                );

                if(isAction)
                    sb.Append("</i>");
                break;

            case "user:connect":
            case "SharpChat.Events.UserConnectEvent":
                sb.Append("-1\tChatBot\tinherit\t\t0\fjoin\f");
                sb.Append(msg.SenderLegacyName);
                break;

            case "chan:join":
            case "SharpChat.Events.UserChannelJoinEvent":
                sb.Append("-1\tChatBot\tinherit\t\t0\fjchan\f");
                sb.Append(msg.SenderLegacyName);
                break;

            case "chan:leave":
            case "SharpChat.Events.UserChannelLeaveEvent":
                sb.Append("-1\tChatBot\tinherit\t\t0\flchan\f");
                sb.Append(msg.SenderLegacyName);
                break;

            case "user:disconnect":
            case "SharpChat.Events.UserDisconnectEvent":
                sb.Append("-1\tChatBot\tinherit\t\t0\f");

                switch((UserDisconnectS2CPacket.Reason)msg.Data.RootElement.GetProperty("reason").GetByte()) {
                    case UserDisconnectS2CPacket.Reason.Flood:
                        sb.Append("flood");
                        break;
                    case UserDisconnectS2CPacket.Reason.Kicked:
                        sb.Append("kick");
                        break;
                    case UserDisconnectS2CPacket.Reason.TimeOut:
                        sb.Append("timeout");
                        break;
                    case UserDisconnectS2CPacket.Reason.Leave:
                    default:
                        sb.Append("leave");
                        break;
                }

                sb.Append('\f');
                sb.Append(msg.SenderLegacyName);
                break;
        }

        sb.Append('\t');
        sb.Append(msg.Id);
        sb.Append('\t');
        sb.Append(notify ? '1' : '0');
        sb.AppendFormat(
            "\t1{0}0{1}{2}",
            isAction ? '1' : '0',
            isAction ? '0' : '1',
            isPrivate ? '1' : '0'
        );

        return sb.ToString();
    }
}