/*
 * Feed.vala
 * 
 * Represents an RSS/Atom feed with its metadata and items.
 * Following GNOME HIG naming conventions and Vala/GObject patterns.
 */

/**
 * Feed - Represents an RSS/Atom feed
 */
public class RSSuper.Feed : Object {
    public string id { get; set; }
    public string title { get; set; }
    public string? link { get; set; }
    public string? description { get; set; }
    public string? subtitle { get; set; }
    public string? language { get; set; }
    public string? last_build_date { get; set; }
    public string? updated { get; set; }
    public string? generator { get; set; }
    public int ttl { get; set; }
    public string raw_url { get; set; }
    public string? last_fetched_at { get; set; }
    public string? next_fetch_at { get; set; }
    public FeedItem[] items { get; set; }
    
    /**
     * Default constructor
     */
    public Feed() {
        this.id = "";
        this.title = "";
        this.raw_url = "";
        this.ttl = 60;
        this.items = {};
    }
    
    /**
     * Constructor with initial values
     */
    public Feed.with_values(string id, string title, string raw_url,
                             string? link = null, string? description = null,
                             string? subtitle = null, string? language = null,
                             string? last_build_date = null, string? updated = null,
                             string? generator = null, int ttl = 60,
                             FeedItem[]? items = null, string? last_fetched_at = null,
                             string? next_fetch_at = null) {
        this.id = id;
        this.title = title;
        this.link = link;
        this.description = description;
        this.subtitle = subtitle;
        this.language = language;
        this.last_build_date = last_build_date;
        this.updated = updated;
        this.generator = generator;
        this.ttl = ttl;
        this.items = items;
        this.raw_url = raw_url;
        this.last_fetched_at = last_fetched_at;
        this.next_fetch_at = next_fetch_at;
    }
    
    /**
     * Add an item to the feed
     */
    public void add_item(FeedItem item) {
        var new_items = new FeedItem[this.items.length + 1];
        for (var i = 0; i < this.items.length; i++) {
            new_items[i] = this.items[i];
        }
        new_items[this.items.length] = item;
        this.items = new_items;
    }
    
    /**
     * Get item count
     */
    public int get_item_count() {
        return this.items.length;
    }
    
    /**
     * Serialize to JSON string
     */
    public string to_json_string() {
        var sb = new StringBuilder();
        sb.append("{");
        sb.append("\"id\":\"");
        sb.append(this.id);
        sb.append("\",\"title\":\"");
        sb.append(this.title);
        sb.append("\",\"raw_url\":\"");
        sb.append(this.raw_url);
        sb.append("\"");
        
        if (this.link != null) {
            sb.append(",\"link\":\"");
            sb.append(this.link);
            sb.append("\"");
        }
        if (this.description != null) {
            sb.append(",\"description\":\"");
            sb.append(this.description);
            sb.append("\"");
        }
        if (this.subtitle != null) {
            sb.append(",\"subtitle\":\"");
            sb.append(this.subtitle);
            sb.append("\"");
        }
        if (this.language != null) {
            sb.append(",\"language\":\"");
            sb.append(this.language);
            sb.append("\"");
        }
        if (this.last_build_date != null) {
            sb.append(",\"lastBuildDate\":\"");
            sb.append(this.last_build_date);
            sb.append("\"");
        }
        if (this.updated != null) {
            sb.append(",\"updated\":\"");
            sb.append(this.updated);
            sb.append("\"");
        }
        if (this.generator != null) {
            sb.append(",\"generator\":\"");
            sb.append(this.generator);
            sb.append("\"");
        }
        if (this.ttl != 60) {
            sb.append(",\"ttl\":%d".printf(this.ttl));
        }
        if (this.items.length > 0) {
            sb.append(",\"items\":[");
            for (var i = 0; i < this.items.length; i++) {
                if (i > 0) sb.append(",");
                sb.append(this.items[i].to_json_string());
            }
            sb.append("]");
        }
        if (this.last_fetched_at != null) {
            sb.append(",\"lastFetchedAt\":\"");
            sb.append(this.last_fetched_at);
            sb.append("\"");
        }
        if (this.next_fetch_at != null) {
            sb.append(",\"nextFetchAt\":\"");
            sb.append(this.next_fetch_at);
            sb.append("\"");
        }
        
        sb.append("}");
        return sb.str;
    }
    
    /**
     * Deserialize from JSON string
     */
    public static Feed? from_json_string(string json_string) {
        var parser = new Json.Parser();
        try {
            if (!parser.load_from_data(json_string)) {
                return null;
            }
        } catch (Error e) {
            warning("Failed to parse JSON: %s", e.message);
            return null;
        }
        
        return from_json_node(parser.get_root());
    }
    
    /**
     * Deserialize from Json.Node
     */
    public static Feed? from_json_node(Json.Node node) {
        if (node.get_node_type() != Json.NodeType.OBJECT) {
            return null;
        }
        
        var obj = node.get_object();
        
        if (!obj.has_member("id") || !obj.has_member("title") || !obj.has_member("raw_url")) {
            return null;
        }
        
        var feed = new Feed();
        feed.id = obj.get_string_member("id");
        feed.title = obj.get_string_member("title");
        feed.raw_url = obj.get_string_member("raw_url");
        
        if (obj.has_member("link")) {
            feed.link = obj.get_string_member("link");
        }
        if (obj.has_member("description")) {
            feed.description = obj.get_string_member("description");
        }
        if (obj.has_member("subtitle")) {
            feed.subtitle = obj.get_string_member("subtitle");
        }
        if (obj.has_member("language")) {
            feed.language = obj.get_string_member("language");
        }
        if (obj.has_member("lastBuildDate")) {
            feed.last_build_date = obj.get_string_member("lastBuildDate");
        }
        if (obj.has_member("updated")) {
            feed.updated = obj.get_string_member("updated");
        }
        if (obj.has_member("generator")) {
            feed.generator = obj.get_string_member("generator");
        }
        if (obj.has_member("ttl")) {
            feed.ttl = (int)obj.get_int_member("ttl");
        }
        if (obj.has_member("lastFetchedAt")) {
            feed.last_fetched_at = obj.get_string_member("lastFetchedAt");
        }
        if (obj.has_member("nextFetchAt")) {
            feed.next_fetch_at = obj.get_string_member("nextFetchAt");
        }
        
        // Deserialize items
        if (obj.has_member("items")) {
            var items_array = obj.get_array_member("items");
            var items = new FeedItem[items_array.get_length()];
            for (var i = 0; i < items_array.get_length(); i++) {
                var item_node = items_array.get_element(i);
                var item = FeedItem.from_json_node(item_node);
                if (item != null) {
                    items[i] = item;
                }
            }
            feed.items = items;
        }
        
        return feed;
    }
    
    /**
     * Equality comparison
     */
    public bool equals(Feed? other) {
        if (other == null) {
            return false;
        }
        
        return this.id == other.id &&
               this.title == other.title &&
               this.link == other.link &&
               this.description == other.description &&
               this.subtitle == other.subtitle &&
               this.language == other.language &&
               this.last_build_date == other.last_build_date &&
               this.updated == other.updated &&
               this.generator == other.generator &&
               this.ttl == other.ttl &&
               this.raw_url == other.raw_url &&
               this.last_fetched_at == other.last_fetched_at &&
               this.next_fetch_at == other.next_fetch_at &&
               this.items_equal(other.items);
    }
    
    /**
     * Helper for item array comparison
     */
    private bool items_equal(FeedItem[] other) {
        if (this.items.length != other.length) {
            return false;
        }
        
        for (var i = 0; i < this.items.length; i++) {
            if (!this.items[i].equals(other[i])) {
                return false;
            }
        }
        
        return true;
    }
}
