/*
 * vdr-podcatcher - A plugin for the Linux Video Disk Recorder
 * Copyright (c) 2006 Tobias Grimm <vdr@e-tobi.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * $Id: rssfeedparser.cc 3219 2006-04-16 15:06:35Z svntobi $
 *
 */

#include <libxml/encoding.h>
#include "rssfeedparser.h"
#include "htmltotext.h"
#include "feed.h"
#include "downloadcache.h"

using namespace std;

RssFeedParser::RssFeedParser(IDownloadCache& downloadCache)
:downloadCache(downloadCache)
{
}

bool RssFeedParser::Parse(Feed& feed)
{
    ref_ptr<istream> rssStream(downloadCache.CreateStreamByUrl(feed.GetUrl()));

    if (rssStream.get())
    {
        xmlpp::DomParser parser;
        parser.set_substitute_entities();
        try
        {
            parser.parse_stream(*rssStream);
            xmlpp::Node& rssRootNode = *(parser.get_document()->get_root_node());
            ParseRssDoc(rssRootNode, feed);
            return true;

        }
        catch (...)
        {
            return false;
        }
    }
    else
    {
        return false;
    }
}

void RssFeedParser::ParseRssDoc(xmlpp::Node& rssRootNode, Feed& feed)
{
    feed.SetTitle(GetChildText(rssRootNode, "channel/title"));

    xmlpp::NodeSet itemNodes = rssRootNode.find("channel/item");

    for(xmlpp::NodeSet::iterator i = itemNodes.begin();
        i != itemNodes.end(); ++i)
    {
        string itemTitle = GetChildText(**i, "title");
        string description = HtmlToText::Convert(GetChildText(**i, "description"));
        string date = GetChildText(**i, "pubDate");

        string enclosure = "";
        if ("audio/mpeg" == GetChildAttributeValue(**i, "enclosure", "type"))
        {
            enclosure = GetChildAttributeValue(**i, "enclosure", "url");
        }

        Item item(itemTitle, Rfc822DateTime(date), description, enclosure);
        feed.AddItem(item);
    }
}

string RssFeedParser::GetChildText(xmlpp::Node& parent, string childPath)
{
    xmlpp::NodeSet nodes = parent.find(childPath + "/text()");
    if (nodes.size() > 0)
    {
        const xmlpp::ContentNode* nodeText =
          dynamic_cast<const xmlpp::ContentNode*>(nodes[0]);

	if (nodeText)
	{
            char* str = strdup(nodeText->get_content().c_str());
            int bufLen = strlen(str);
	    int strLen = xmlUTF8Strlen((xmlChar*) str);
            UTF8Toisolat1((xmlChar*) str, &strLen, (xmlChar*) str, &bufLen);
            str[strLen] = 0;

            string returnValue = str;

            free(str);

            return returnValue;
	}
    }
    return "";
}

string RssFeedParser::GetChildAttributeValue(xmlpp::Node& parent, string childPath,
  string attributeName)
{
    xmlpp::NodeSet nodes = parent.find(childPath);
    if (nodes.size() > 0)
    {
        const xmlpp::Element* element =
          dynamic_cast<const xmlpp::Element*>(nodes[0]);

        if (element)
	{
            xmlpp::Attribute* attribute = element->get_attribute(attributeName);
            if (attribute)
            {
                return attribute->get_value();
            }
	}
    }
    return "";
}
