/* 
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. 
 * 
 * This file is available and licensed under the following license:
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice, 
 *     this list of conditions and the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *
 *   * Neither the name of Sun Microsystems nor the names of its contributors 
 *     may be used to endorse or promote products derived from this software 
 *     without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package podcastfeedviewer;

/**
 * @author Raghu Nair
 */
import java.io.InputStream;
import java.lang.Integer;
import javafx.data.pull.Event;
import javafx.data.feed.atom.AtomTask;
import javafx.data.feed.atom.Feed;
import javafx.data.feed.FeedTask;
import javafx.data.feed.atom.Entry;
import javafx.scene.media.Media;
import javafx.data.pull.PullParser;
import javafx.io.http.HttpRequest;
import javafx.data.feed.rss.RssTask;
import javafx.data.feed.rss.Channel;
import javafx.data.feed.rss.Item;
import java.util.Hashtable;
import java.lang.RuntimeException;


//all the valid podcast feeds
var podcastFeeds:Hashtable = new Hashtable();

public def ATOM = 1;

public def RSS  = 2;

//Get all Medias for a given location.
public function getMedias(location:String):PodcastMedia[] {
    var pf =  podcastFeeds.get(location) as PodcastFeed;
    if ( pf != null ){
        return pf.medias;
    }else {
        throw new RuntimeException("{location} may not be a RSS feed");
    }
}

/* podcastFeed for the given location*/
public function getPodcastFeed(location:String):PodcastFeed{
    return podcastFeeds.get(location) as PodcastFeed;
}

/* add a podcast will be called during the start up time
 * to add the persisted locations */
public function addPodcast(location:String){
    Main.mediaBox.loading = true;
    PodcastParser{
        location:location
        isFromPersistenceStore:true
    }
}

/* Remove a podcast from memory */
public function removePodcast(location:String){
    var podcastFeed = getPodcastFeed(location);
    if (podcastFeed.feedTask.started ){
        podcastFeed.feedTask.stop();
    }
    podcastFeeds.remove(location);
    delete location from Main.locations;
}

/* Podcast Parser */
public class PodcastParser {

    //RSS/Atom FeedTask associated with it.
    public var feedTask:FeedTask ;

    //used during the initial creation.
    public-init var isFromPersistenceStore:Boolean = false;

    /* Indicates is parsing done for the current feed*/
    public-read var isDone :Boolean = false on replace {
        if ( isDone and podcastFeed.medias != null and sizeof podcastFeed.medias > 0){
            //This can be called in two cases
            //1 - for the first time - which is covered in else loop
            //2 - if there is a change in the feed. - if loop.
            if ( podcastFeeds.get(location) != null ){
                podcastFeeds.remove(location);
            }else {
                Main.log("Parsing Done adding {location} to feed list");
                Main.currentPodcastFeed = podcastFeed;
                Main.log("Podcast Title - {Main.currentPodcastFeed.title}");
                insert location into Main.locations;
                //If loading for the first time.
                if ( not isFromPersistenceStore){
                    //Add this location to Persistence store.
                    PersistenceHandler.store(location);
                }
            }      
            podcastFeeds.put(podcastFeed.location,podcastFeed);
            
        }
        if (isDone){
            Main.mediaBox.loading = false;
        }
    }

    /* Current Feed */
    public-read var podcastFeed:PodcastFeed;


    /* RSS or Atom Feed Location */
    public-init var location:String on replace {
        FeedValidator{  
            podcastParser: this
            location:location
        }.start()
    }


    /* Indicates Atom or RSS */
    public var type:Integer on replace {

        if ( type == ATOM ){
            feedTask = AtomTask{
                location:location;
                interval:Main.feedInterval;
                onFeed: function(feed:Feed){
                    Main.log("Feed - {feed}");
                    podcastFeed.title = feed.title.text;
                }

                onEntry: function(entry:Entry){
                    Main.log(" Entry - {entry}");
                    var length:Long ;
                    var mediaURL = null;
                    var apptype = null;
                    var media:PodcastMedia = null;
                    for (link in entry.links){
                        Main.log("Link - {link}");
                        
                        if ( link.type != null and 
                            (link.type.trim().startsWith("audio") or
                            link.type.trim().startsWith("video")) )  {
                            Main.log("link.type - {link.type}");
                            apptype  = link.type;
                        }else {
                            continue;
                        }

                        Main.log("link.length - {link.length}");

                        try {
                            if ( link.length != null and
                                not link.length.trim().equals("")) {
                                length = Long.parseLong(link.length);
                            }else {
                                length = 0;
                            }
                        }catch (e){ length = 0}

                        if ( link.href != null ){
                            Main.log("link.href - {link.href}");
                            mediaURL = link.href;
                            insert
                            (media = PodcastMedia{
                                length:length
                                mediaURL:mediaURL
                                type:apptype })
                            into podcastFeed.medias;
                            Main.log ("Adding Media {mediaURL}");
                        }
                        if ( link.title != null and link.title != "") {
                            media.title = link.title;
                        }
                    }
                    if ( media != null ){
                        if ( media.title == null ){
                            media.title = entry.title.text;
                        }
                        media.data =  entry.summary.text;
                    }
                }
            }
        }else if ( type == RSS ) {
            feedTask = RssTask{
                location:location

                interval:Main.feedInterval

                onChannel:function(channel:Channel){
                    Main.log("Channel - {channel}");
                    podcastFeed.title = channel.title;
                    podcastFeed.description = channel.description;
                }
                onItem:function(item:Item){
                    Main.log("item - {item}");
                    var media:PodcastMedia;
                    var enclosure = item.enclosure;
                    if ( enclosure != null and 
                        (enclosure.type.startsWith("audio") or
                        enclosure.type.startsWith("video") ) and 
                        enclosure.url.startsWith("http")) {
                        media = PodcastMedia{
                            mediaURL: enclosure.url
                            type: enclosure.type
                            length: enclosure.length
                        }
                    }else return;
                    media.title = item.title;
                    media.data = item.description;
                    insert  media into podcastFeed.medias;
                }
            }
        }
        if ( feedTask != null ){
            //Create podcast feed for Atom/RSS.
            podcastFeed = PodcastFeed{location:location  feedTask:feedTask}
            feedTask.start();
            feedTask.onDone = function(){
                isDone = true;
            }

        }else {
            if ( type == -1)
                throw new RuntimeException("Not a RSS/Atom Feed - {location}");
        }
    }
}