/*
 * 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: podcatcherplugin_test.cc 3407 2006-04-26 18:08:29Z svntobi $
 *
 */

#include "i18n.h"
#include <cxxtest/TestSuite.h>
#include "vdr-stub/pluginhooks.h"
#include "podcatcherplugin.h"
#include "threadmock.h"
#include "servicelocatorstub.h"
#include "feedupdatermock.h"
#include "errorlogger.h"
#include "downloadcachemock.h"
#include "vdr-stub/menusetuppagestub.h"

using namespace std;

namespace
{
    class ErrorLoggerStub: public IErrorLogger
    {
        public:
            string lastLogMessage;

        public:
            // <IErrorLogger>
            void Log(string Message)
            {
                lastLogMessage = Message;
            }
            // </IErrorLogger>
    };

    class PodcatcherTest: public CxxTest::TestSuite
    {
        private:
            PodcatcherPlugin* plugin;
            ServiceLocatorStub* serviceLocator;
            ErrorLoggerStub errorLoggerStub;

        public:
            void setUp()
            {
                serviceLocator = new ServiceLocatorStub();
                plugin = new PodcatcherPlugin;
                plugin->SetServiceLocator(
                  ref_ptr<IServiceLocator>(serviceLocator));
                serviceLocator->errorLogger = &errorLoggerStub;
            }

            void tearDown()
            {
                system("rmdir ./notWritable 2>/dev/null");
                delete plugin;
            }

            void TestMainMenuEntry()
            {
                TS_ASSERT_EQUALS(string("i18n:Podcatcher"), plugin->MainMenuEntry());
            }

            void TestVersion()
            {
                TS_ASSERT_EQUALS(string("0.1.1"), plugin->Version());
            }

            void TestDescription()
            {
                TS_ASSERT_EQUALS(string("i18n:Download and play podcasts"),
                  plugin->Description());
            }

            void TestInitializeRegistersI18nPhrases()
            {
                char* argv[2] = {"dummy", "--cache=."};
                TS_ASSERT(plugin->ProcessArgs(2, argv));
                TS_ASSERT(plugin->Initialize());
                TS_ASSERT_EQUALS(Phrases, PluginHooks::Phrases);
            }

            void TestSourcesFileName()
            {
                char* argv[2] = {"dummy", "--cache=."};
                TS_ASSERT(plugin->ProcessArgs(2, argv));
                TS_ASSERT(plugin->Initialize());
                TS_ASSERT_EQUALS("/vdrstub/podcatchersources.conf",
                  plugin->GetSourcesFileName());
            }

            void TestMainMenuAction()
            {
                cOsdMenu menu("");
                serviceLocator->feedMenu = &menu;
                TS_ASSERT_EQUALS(&menu, plugin->MainMenuAction());
            }

            void TestSetupMenuAction()
            {
                MenuSetupPageStub setupMenu;
                serviceLocator->setupMenu = &setupMenu;
                TS_ASSERT_EQUALS(&setupMenu, plugin->SetupMenu());
            }

            void TestStartRunsDownloadThreadAndUpdatesFeeds()
            {
                ThreadMock downloadThread;
                FeedUpdaterMock feedUpdater;

                serviceLocator->downloadThread = &downloadThread;
                serviceLocator->feedUpdater = &feedUpdater;

                downloadThread.ExpectMethod("Start");
                feedUpdater.ExpectMethod("Update");

                TS_ASSERT(plugin->Start());

                downloadThread.Verify();
                feedUpdater.Verify();
            }

            void TestHousekeepingUpdatesFeeds()
            {
                FeedUpdaterMock feedUpdater;
                serviceLocator->feedUpdater = &feedUpdater;
                DownloadCacheMock downloadCache;
                serviceLocator->downloadCache = &downloadCache;

                feedUpdater.ExpectMethod("Update");
                plugin->Housekeeping();
                feedUpdater.Verify();
            }

            void TestHousekeepingCleansCache()
            {
                FeedUpdaterMock feedUpdater;
                serviceLocator->feedUpdater = &feedUpdater;
                DownloadCacheMock downloadCache;
                serviceLocator->downloadCache = &downloadCache;
                plugin->SetupParse("MaxCacheAge", "10");

                downloadCache.ExpectMethod("CleanUp",
                  downloadCache.MakeString(10 * 24));
                plugin->Housekeeping();
                downloadCache.Verify();
            }

            void TestInitializeFailsWithErrorMessageIfCacheDirNotExisting()
            {
                char* argv[2] = {"dummy", "--cache=/foo/notExisting"};
                errorLoggerStub.lastLogMessage = "";

                TS_ASSERT(plugin->ProcessArgs(2, argv));
                TS_ASSERT(!plugin->Initialize());
                TS_ASSERT_EQUALS("Unable to access cache directory "
                  "`/foo/notExisting`", errorLoggerStub.lastLogMessage);
            }

            void TestInitializeFailsWithErrorMessageIfCacheDirNotWritable()
            {
                char* argv[2] = {"dummy", "--cache=./notWritable"};
                system("mkdir ./notWritable");
                system("chmod a-w ./notWritable");
                errorLoggerStub.lastLogMessage = "";

                TS_ASSERT(plugin->ProcessArgs(2, argv));
                TS_ASSERT(!plugin->Initialize());
                TS_ASSERT_EQUALS("Unable to access cache directory "
                  "`./notWritable`", errorLoggerStub.lastLogMessage);
            }

            void TestSetupParseFailsForUnknownSetting()
            {
                TS_ASSERT(!plugin->SetupParse("unknown setting", "value"));
            }

            void TestDefaultMaxCacheAge()
            {
                TS_ASSERT_EQUALS(30, plugin->GetMaxCacheAge());
            }

            void TestSetupParseMaxCacheAge()
            {
                TS_ASSERT(plugin->SetupParse("MaxCacheAge", "10"));
                TS_ASSERT_EQUALS(10, plugin->GetMaxCacheAge());
            }
        };
};
