#include "RSSExample.h"

//**********************************************************************************************
//* RssExample implementation.
//* --------------------------
//* This Example demonstarates, creating and parsing a multi-channel rss (v2.0) feed.
//* 
//*

void RSSExample::ComposeRss()
{	
	// Rss class allows multiple channels in a feed.
	RssChannel channel1, channel2;

	channel1
		.Title("Auto-created rss channel")														// Channel title											
		.Link ("http://www.rssboard.org/rss-specification")										// Channel link
		.Description("For more information on Rss, follow the supplied link.")					// Channel description
		.Language("en-us")																		// Channel language
		.Copyright("Channel copyright.")														// Channel copyright info
		.Generator("Generated by Rss parser/composer class. (Powered by Ultimate++).")			// Rss generator info
		.Category(RssCategory("no category specified."))										// Channel category
		.TTL(60)																				// Channel time-to-live
		.SkipDays("Mon")																		// Channel skipdays item 1 (max 7);
		.SkipDays("Tue")																		// Channel skipdays item 2;
		.SkipHours(1)																			// Channel skiphours item 1 (1-24)
		.SkipHours(2)
		.Image(													
		        RssImage(																		// Channel image		
				"Channel image title.",															// Channel image title
				"Link to the website that offers the channel",									// Channel image link
				"URL to the image",																// Channel image url
				"This element usually contains the channel image/logo",							// Channel image description
				Size(10, 20) 																	// Channel image size
				));
				
	for(int i = 1; i < 5; i++) {
		RssTag cat = RssCategory(Format("Item %d has a category", i));
		channel1
			.Item(
				RssItem(
			 	Format("Item %d", i),															// Item title 
			 	Format("http://www.rsssource/item%d.html", i),									// Item link 
			 	Format("This is a RSS item no %d", i),											// Item description
			 	Format("Item %d has an author", i),												// Item author
			 	NULL,																			// Item comment
			 	NULL,																			// Item publication date				 	
			 	(i < 3 ? &cat : NULL)				// Item category
			 	));																				
	}

	// Create a copy of the channel
	// Rss class and it's related sub-classes (RssTag, RssNode and RssChannel) 
	// have their assignment operator ('=') defined (easy way to copy stuff).
	channel2 = channel1;

	// Add the channels to the feed.
	rss	.Channel(channel1)
		.Channel(channel2);
	
	// Compose the Rss feed.
	String feed;
	if(!rss.Compose(feed))
		Exclamation(rss.GetError());
	
	// Parse the crteated Rss feed.
	ParseRss(feed);

}

void RSSExample::ParseRss(String& feed)
{
	// Clear the TreeCtrl.
	tree.NoRoot();
	tree.Clear();

	// Parse the Rss feed.
	if(!rss.Parse(feed)) {
		tree.Add(0, Null, "Parsing Error: " + rss.GetError());
		return;
	}
	
	// There are two ways to get datta from a Rss class in parser state.
	// 1) Using element (or if you prefer "tag") specific methods:
	int rssid = tree.Add(0, Null, 
						Format("RSS (v%s) structure, encoding: (%s)",
	                   	rss.Version(),
	                   	rss.Encoding())
	                   );
	                   
	// Rss class supports mult-channel feeds.
	RssChannels& channels = rss.Channels();
	String attributes;
	for(int i = 0; i < channels.GetCount(); i++) {
		int chid = tree.Add(rssid, Null, Format("CHANNEL (%d)", i + 1));
		GetRssTags(chid, channels[i].Tags());
		GetRssNodes(chid, channels[i].Nodes());
	}

	tree.OpenDeep(0);
	
	// Also, show raw rss source in ASCII 
	edit.Set(feed);
}

void RSSExample::GetRssTags(int parent, RssTags& tags)
{
	for(int i = 0; i < tags.GetCount(); i++) {
		tree.Add(parent, Null, 
			Format("Element<%s>: %s %s", 
			ToUpper(tags[i].Tag()), 
			tags[i].Text(), 
			GetTagAttrs(tags[i]))
		);
	}
}

void RSSExample::GetRssNodes(int parent, RssNodes& nodes)
{
	for(int i = 0; i < nodes.GetCount(); i++) {
		int nid = tree.Add(parent, Null, 
			Format("NODE <%s>", nodes[i].Tag())
		);
		if(nodes[i].HasTag())
			GetRssTags(nid, nodes[i].Tags());
		if(nodes[i].HasNode()) 
			GetRssNodes(nid, nodes[i].Nodes());
	}
}

String RSSExample::GetTagAttrs(RssTag& tag)
{
	String out = Null;
	if(tag.HasAttr()) {
		RssAttributes& attrs = tag.Attrs();
		for(int i = 0; i < attrs.GetCount(); i++) {
			String key, val;
			val = attrs.Get(key = attrs.GetKey(i));
			out << key << ": (" << val << ") ";		                
		}
	}
	return out;
}

RSSExample::RSSExample() {

	CtrlLayout(*this, "RSS Parser/Composer Example");
	Sizeable().Zoomable();
	splitter.Horz();
	splitter << edit << tree;
	
	// Compose and parse a Rss Feed.	
	ComposeRss();
}

GUI_APP_MAIN {

	RSSExample().Run();
}

