using GLib;
using Gee;

public class Message : Object, Comparable<Message>, Hashable<Message>
{
    public string guid { get; set; default = ""; }
    public string text { get; set; default = ""; }
    public DateTime date { get; set; default = new DateTime.now_local(); }
    public string sender { get; set; default = null; }
    
    public Attachment[] attachments { get; set; default = {}; }

    public bool should_animate = false;

    public bool from_me {
        get {
            // Hm, this may have been accidental. 
            return sender == "(Me)";
        }
    }

    public bool is_attachment_marker {
        get {
            uint8[] attachment_marker_str = { 0xEF, 0xBF, 0xBC, 0x00 };
            if (text.length > attachment_marker_str.length) {
                return false;
            }
            
            return (string)attachment_marker_str == text;
        }
    }

    public string markup {
        owned get {
            const string link_regex_pattern = "https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)";
        
            try {
                var regex = new GLib.Regex(link_regex_pattern);
    
                var escaped_text = GLib.Markup.escape_text(this.text);
                return regex.replace(escaped_text, escaped_text.length, 0, "<u>\\0</u>");
            } catch (GLib.RegexError e) {
                GLib.warning("Error linking text: %s", e.message);
                return GLib.Markup.escape_text(this.text);
            }
        }
    }

    public Message(string text, DateTime date, string? sender) {
        this.text = text;
        this.date = date;
        this.sender = sender;
    }

    public Message.from_hash_table(HashTable<string, Variant> message_data) {
        guid = message_data["id"].get_string();
        text = message_data["text"].get_string();
        sender = message_data["sender"].get_string();
        date = new DateTime.from_unix_utc(message_data["date"].get_int64());

        // Attachments
        var attachments_variant = message_data["attachments"];
        var attachments = new Gee.ArrayList<Attachment>();
        if (attachments_variant != null) {
            for (int i = 0; i < attachments_variant.n_children(); i++) {
                var attachment_variant = attachments_variant.get_child_value(i);
                var attachment = new Attachment.from_variant(attachment_variant);
                attachments.add(attachment);
            }
        }

        this.attachments = attachments.to_array();
    }

    public int compare_to(Message other) {
        if (guid == other.guid) {
            return 0;
        }

        return 1;
    }

    public bool equal_to(Message other) {
        return guid == other.guid;
    }

    public uint hash() {
        return guid.hash();
    }
}