/* possible RSS parsers:

https://npmjs.org/package/feedparser
https://npmjs.org/package/nodepie
https://npmjs.org/package/feedr

(there are many more, these looked the most promising)
*/


var Q = require("q");
var request = require("request");
var feedparser = require("feedparser");
var endpoint = require("endpoint");

var dataUserPostsRead = require("./data/userPostsRead.js");
var dataRssUrlStatus = require("./data/rssUrlStatus.js");
var dataFeedPosts = require("./data/feedPosts.js");

module.exports = function(app) {

    app.all("/posts*", function(req, res, next){

        if (typeof req.user !== "object") {
            next(new Error("Unauthenticated request made to posts."));
            return;
        }

        req.rssUrl = req.param("rssUrl", null);
        if (req.rssUrl === null) {
            res.status(400).send("Expected parameter rssUrl");
            return;
        }

        next();
    });

    app.get("/posts", function(req, res, next) {

        loadFeedsThroughDatabase(req.rssUrl, req.user.id, new Date())
            .then(function(results) {
                res.setHeader("Content-Type", "application/json");
                res.send(JSON.stringify(results));
            }, function(err) {
                res.setHeader("Content-Type", "application/json");
                res.send(JSON.stringify([]));
            });
    });

    app.post("/posts/finished", function(req,res,next) {

        dataUserPostsRead.markPostAsRead(req.user.id, req.rssUrl)
        .then(function() {
            res.status(200).send("ok");
        }, function(err) {
            next(err);
        });
    });

    app.post("/posts/unfinished", function(req,res,next) {

        dataUserPostsRead.markPostAsUnread(req.user.id, req.rssUrl)
        .then(function() {
            res.status(200).send("ok");
        }, function(err) {
            next(err);
        });
    });
};

function loadMeta(rssUrl) {

    var deferred = Q.defer();

    request(rssUrl, function(error, response, body) {
        if (error !== null) {
            deferred.reject(error);
        } else if (Math.floor(response.statusCode / 100) !== 2) {
            deferred.reject("Expected 200 response code, was " + response.statusCode);
        }
    })
    .on('error', function(err) { deferred.reject(err); })
    .pipe(feedparser({
            feedurl: rssUrl
        }))
    .on('error', function(err) { deferred.reject(err); })
    .on('meta', function(meta) {
        deferred.resolve({
            feedName : meta.title,
            feedLink : meta.link || rssUrl
        });
    });

    return deferred.promise;
}

module.exports.loadMeta = loadMeta;

function loadFeeds(rssUrl) {

    var deferred = Q.defer();

    request(rssUrl, function(error, response, body) {
        if (error !== null) {
            deferred.reject(error);
        } else if (Math.floor(response.statusCode / 100) !== 2) {
            deferred.reject("Expected 200 response code, was " + response.statusCode);
        }
    })
    .on('error', function(err) { deferred.reject(err); })
    .pipe(feedparser({
            feedurl: rssUrl
        }))
    .on('error', function(err) { deferred.reject(err); })
    .pipe(endpoint({
            objectMode: true
        }, function(err, results) {

            try {
                if (err !== null) {
                    deferred.reject(err);
                } else {

                    var mappedResults = results.map(function(val) {
                        return {
                            feedName: val.meta.title,
                            postName: val.title,
                            postUrl: val.link,
                            postDate: val.date
                        };
                    });

                    deferred.resolve(mappedResults);
                }
            } catch (e) {
                deferred.reject(e);
            }
        }));

    return deferred.promise;
}

module.exports.loadFeeds = loadFeeds;

function loadFeedsThroughDatabase(rssUrl, userId, readTime) {

    return Q()
    .then(function() {
        return dataRssUrlStatus.checkIfUrlNeedsUpdate(rssUrl, readTime)
        .then(function(result) {
            
            if (result) {
                
                return loadFeeds(rssUrl)
                .then(function(posts){
                    return dataFeedPosts.writePostsToDatabase(rssUrl, posts)
                    .then(function() {
                        return dataRssUrlStatus.writeRssUrlStatus(rssUrl, "ok", readTime);
                    });
                })
                .fail(function(err) {
                    return dataRssUrlStatus.writeRssUrlStatus(rssUrl, err.toString(), readTime);
                });
            }
        });
    })
    .then(function() {
        return dataFeedPosts.loadPostsFromDatabase(rssUrl, userId);
    });
}


module.exports.loadFeedsThroughDatabase = loadFeedsThroughDatabase;


@@ -4227,32 +4227,242 @@
                %0A
+                return Q()%0A                .then(function() %7B%0A                    return dataFeedPosts.getLastPostDate(rssUrl);%0A                %7D)%0A                .then(function(previouslyLatestPostDate) %7B%0A    
                 
@@ -4478,32 +4478,36 @@
 adFeeds(rssUrl)%0A
+    
                 
@@ -4529,16 +4529,454 @@
 posts)%7B%0A
+%0A
+                        // use the previously observed last post date to filter%0A                        // any posts that may look new because their url changed%0A                        if (previouslyLatestPostDate !== null) %7B%0A                            posts = posts.filter(function(post) %7B%0A                                return post.postDate %3E= previouslyLatestPostDate;%0A                            %7D);%0A                        %7D%0A%0A    
         
@@ -5044,16 +5044,20 @@
  posts)%0A
+    
         
@@ -5103,32 +5103,36 @@
                 
+    
 return dataRssUr
@@ -5174,32 +5174,60 @@
 ok%22, readTime);%0A
+                        %7D);%0A
                 

use the last observed post publication date to filter posts that are republished with a new url