/*
 * SearchResult.vala
 * 
 * Represents a search result item from the feed database.
 * Following GNOME HIG naming conventions and Vala/GObject patterns.
 */

/**
 * SearchResultType - Type of search result
 */
public enum RSSuper.SearchResultType {
    ARTICLE,
    FEED
}

/**
 * SearchResult - Represents a single search result
 */
public class RSSuper.SearchResult : Object {
    public string id { get; set; }
    public SearchResultType result_type { get; set; }
    public string title { get; set; }
    public string? snippet { get; set; }
    public string? link { get; set; }
    public string? feed_title { get; set; }
    public string? published { get; set; }
    public double score { get; set; }
    
    /**
     * Default constructor
     */
    public SearchResult() {
        this.id = "";
        this.result_type = SearchResultType.ARTICLE;
        this.title = "";
        this.score = 0.0;
    }
    
    /**
     * Constructor with initial values
     */
    public SearchResult.with_values(string id, SearchResultType type, string title,
                                     string? snippet = null, string? link = null,
                                     string? feed_title = null, string? published = null,
                                     double score = 0.0) {
        this.id = id;
        this.result_type = type;
        this.title = title;
        this.snippet = snippet;
        this.link = link;
        this.feed_title = feed_title;
        this.published = published;
        this.score = score;
    }
    
    /**
     * Get type as string
     */
    public string get_type_string() {
        switch (this.result_type) {
            case SearchResultType.ARTICLE:
                return "article";
            case SearchResultType.FEED:
                return "feed";
            default:
                return "unknown";
        }
    }
    
    /**
     * Parse type from string
     */
    public static SearchResultType type_from_string(string str) {
        switch (str) {
            case "article":
                return SearchResultType.ARTICLE;
            case "feed":
                return SearchResultType.FEED;
            default:
                return SearchResultType.ARTICLE;
        }
    }
    
    /**
     * Serialize to JSON string
     */
    public string to_json_string() {
        var sb = new StringBuilder();
        sb.append("{");
        sb.append("\"id\":\"");
        sb.append(this.id);
        sb.append("\",\"type\":\"");
        sb.append(this.get_type_string());
        sb.append("\",\"title\":\"");
        sb.append(this.title);
        sb.append("\"");
        
        if (this.snippet != null) {
            sb.append(",\"snippet\":\"");
            sb.append(this.snippet);
            sb.append("\"");
        }
        if (this.link != null) {
            sb.append(",\"link\":\"");
            sb.append(this.link);
            sb.append("\"");
        }
        if (this.feed_title != null) {
            sb.append(",\"feedTitle\":\"");
            sb.append(this.feed_title);
            sb.append("\"");
        }
        if (this.published != null) {
            sb.append(",\"published\":\"");
            sb.append(this.published);
            sb.append("\"");
        }
        if (this.score != 0.0) {
            sb.append(",\"score\":%f".printf(this.score));
        }
        
        sb.append("}");
        return sb.str;
    }
    
    /**
     * Deserialize from JSON string
     */
    public static SearchResult? 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 SearchResult? 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("type") || !obj.has_member("title")) {
            return null;
        }
        
        var result = new SearchResult();
        result.id = obj.get_string_member("id");
        result.result_type = SearchResult.type_from_string(obj.get_string_member("type"));
        result.title = obj.get_string_member("title");
        
        if (obj.has_member("snippet")) {
            result.snippet = obj.get_string_member("snippet");
        }
        if (obj.has_member("link")) {
            result.link = obj.get_string_member("link");
        }
        if (obj.has_member("feedTitle")) {
            result.feed_title = obj.get_string_member("feedTitle");
        }
        if (obj.has_member("published")) {
            result.published = obj.get_string_member("published");
        }
        if (obj.has_member("score")) {
            result.score = obj.get_double_member("score");
        }
        
        return result;
    }
    
    /**
     * Equality comparison
     */
    public bool equals(SearchResult? other) {
        if (other == null) {
            return false;
        }
        
        return this.id == other.id &&
               this.result_type == other.result_type &&
               this.title == other.title &&
               this.snippet == other.snippet &&
               this.link == other.link &&
               this.feed_title == other.feed_title &&
               this.published == other.published &&
               this.score == other.score;
    }
    
    /**
     * Get a human-readable summary
     */
    public string get_summary() {
        if (this.feed_title != null) {
            return "[%s] %s - %s".printf(this.get_type_string(), this.feed_title, this.title);
        }
        return "[%s] %s".printf(this.get_type_string(), this.title);
    }
}
