#define USE_TRACING
#define DEBUG

using System;
using Google.GData.Blogger;
using Google.GData.Client.UnitTests;
using NUnit.Framework;

namespace Google.GData.Client.LiveTests
{
    [TestFixture]
    [Category("LiveTest")]
    public class BloggerTestSuite : BaseLiveTestClass
    {

        //////////////////////////////////////////////////////////////////////
        /// <summary>the setup method</summary> 
        //////////////////////////////////////////////////////////////////////
        [SetUp]
        public override void InitTest()
        {
            base.InitTest();
            GDataGAuthRequestFactory authFactory = factory as GDataGAuthRequestFactory;
            if (authFactory != null)
            {
                authFactory.Handler = strAuthHandler;
            }
            FeedCleanup(bloggerURI, userName, passWord, VersionDefaults.Major);
        }

        /////////////////////////////////////////////////////////////////////////////

        ////////////////////////////////////////////////////////////////////
        /// <summary>the end it all method</summary> 
        //////////////////////////////////////////////////////////////////////
        [TearDown]
        public override void EndTest()
        {
            Tracing.ExitTracing();
            FeedCleanup(bloggerURI, userName, passWord, VersionDefaults.Major);
        }

        /// <summary>
        ///  test Uri for google calendarURI
        /// </summary>
        protected string bloggerURI;

        //////////////////////////////////////////////////////////////////////

        /////////////////////////////////////////////////////////////////////////////

        //////////////////////////////////////////////////////////////////////
        /// <summary>private void ReadConfigFile()</summary> 
        /// <returns> </returns>
        //////////////////////////////////////////////////////////////////////
        protected override void ReadConfigFile()
        {
            base.ReadConfigFile();

            if (unitTestConfiguration.Contains("bloggerURI"))
            {
                bloggerURI = (string) unitTestConfiguration["bloggerURI"];
                Tracing.TraceInfo("Read bloggerURI value: " + bloggerURI);
            }
        }

        /////////////////////////////////////////////////////////////////////////////

        public override string ServiceName
        {
            get { return "blogger"; }
        }

        /////////////////////////////////////////////////////////////////////////////

        //////////////////////////////////////////////////////////////////////
        /// <summary>tests the etag functionallity for updates</summary> 
        //////////////////////////////////////////////////////////////////////
        [Test]
        public void BloggerETagTest()
        {
            Tracing.TraceMsg("Entering BloggerETagTest");

            BloggerQuery query = new BloggerQuery();
            BloggerService service = new BloggerService(ApplicationName);
            service.ProtocolMajor = 2;

            string title = "V1" + Guid.NewGuid();

            service.RequestFactory = factory;

            query.Uri = new Uri(bloggerURI);

            // insert a new entry in version 1

            AtomEntry entry = ObjectModelHelper.CreateAtomEntry(1);
            entry.Categories.Clear();
            entry.Title.Text = title;
            entry.IsDraft = true;

            BloggerEntry returnedEntry = service.Insert(new Uri(bloggerURI), entry) as BloggerEntry;

            Assert.IsTrue(returnedEntry.ProtocolMajor == service.ProtocolMajor);
            Assert.IsTrue(entry.IsDraft);
            Assert.IsTrue(returnedEntry.IsDraft);
            Assert.IsTrue(returnedEntry.Etag != null);

            string etagOld = returnedEntry.Etag;

            returnedEntry.Content.Content = "This is a test";

            BloggerEntry newEntry = returnedEntry.Update() as BloggerEntry;

            Assert.IsTrue(newEntry.Etag != null);
            Assert.IsTrue(newEntry.Etag != etagOld);
        }

        /////////////////////////////////////////////////////////////////////////////

        //////////////////////////////////////////////////////////////////////
        /// <summary>checks for xhtml persistence</summary> 
        //////////////////////////////////////////////////////////////////////
        [Test]
        public void BloggerHTMLTest()
        {
            Tracing.TraceMsg("Entering BloggerHTMLTest");

            FeedQuery query = new FeedQuery();
            BloggerService service = new BloggerService(ApplicationName);

            if (bloggerURI != null)
            {
                if (userName != null)
                {
                    service.Credentials = new GDataCredentials(userName, passWord);
                }

                service.RequestFactory = factory;

                query.Uri = new Uri(bloggerURI);
                AtomFeed feed = service.Query(query);

                string strTitle = "Dinner time" + Guid.NewGuid();

                if (feed != null)
                {
                    // get the first entry
                    string htmlContent = "<div>&lt;b&gt;this is an html test text&lt;/b&gt;</div>";
                    AtomEntry entry = ObjectModelHelper.CreateAtomEntry(1);
                    entry.Categories.Clear();
                    entry.Title.Text = strTitle;
                    entry.Content.Type = "html";
                    entry.Content.Content = htmlContent;

                    AtomEntry newEntry = feed.Insert(entry);
                    Tracing.TraceMsg("Created blogger entry");

                    // try to get just that guy.....
                    FeedQuery singleQuery = new FeedQuery();
                    singleQuery.Uri = new Uri(newEntry.SelfUri.ToString());
                    AtomFeed newFeed = service.Query(singleQuery);
                    AtomEntry sameGuy = newFeed.Entries[0];

                    Assert.IsTrue(sameGuy.Title.Text.Equals(newEntry.Title.Text), "both titles should be identical");
                    Assert.IsTrue(sameGuy.Content.Type.Equals("html"));
                    string input = HttpUtility.HtmlDecode(htmlContent);
                    string output = HttpUtility.HtmlDecode(sameGuy.Content.Content);
                    Assert.IsTrue(input.Equals(output), "The input string should be equal the output string");

                }

                service.Credentials = null;
            }
        }

        /////////////////////////////////////////////////////////////////////////////

        //////////////////////////////////////////////////////////////////////
        /// <summary>tests if we can access a public feed</summary> 
        //////////////////////////////////////////////////////////////////////
        [Test]
        public void BloggerPublicFeedTest()
        {
            Tracing.TraceMsg("Entering BloggerPublicFeedTest");

            FeedQuery query = new FeedQuery();
            BloggerService service = new BloggerService(ApplicationName);

            string publicURI = (string) externalHosts[0];

            if (publicURI != null)
            {
                service.RequestFactory = factory;

                query.Uri = new Uri(publicURI);
                AtomFeed feed = service.Query(query);

                if (feed != null)
                {
                    // look for the one with dinner time...
                    foreach (AtomEntry entry in feed.Entries)
                    {
                        Assert.IsTrue(entry.ReadOnly, "The entry should be readonly");
                    }
                }
            }

        }

        /////////////////////////////////////////////////////////////////////////////

        //////////////////////////////////////////////////////////////////////
        /// <summary>runs an authentication test</summary> 
        //////////////////////////////////////////////////////////////////////
        [Test]
        public void BloggerStressTest()
        {
            Tracing.TraceMsg("Entering Blogger GoogleStressTest");

            FeedQuery query = new FeedQuery();
            BloggerService service = new BloggerService(ApplicationName);

            if (bloggerURI != null)
            {
                if (userName != null)
                {
                    service.Credentials = new GDataCredentials(userName, passWord);
                }

                service.RequestFactory = factory;

                query.Uri = new Uri(bloggerURI);
                AtomFeed blogFeed = service.Query(query);

                ObjectModelHelper.DumpAtomObject(blogFeed, CreateDumpFileName("AuthenticationTest"));

                if (blogFeed != null)
                {
                    for (int i = 0; i < 30; i++)
                    {
                        AtomEntry entry = ObjectModelHelper.CreateAtomEntry(i);
                        entry.Categories.Clear();
                        entry.Title.Text = "Title " + i;
                        entry.Content.Content = "Some text...";
                        entry.Content.Type = "html";

                        blogFeed.Insert(entry);
                    }
                }
            }

        }

        /////////////////////////////////////////////////////////////////////////////

        //////////////////////////////////////////////////////////////////////
        /// <summary>tests if we can access a public feed</summary> 
        //////////////////////////////////////////////////////////////////////
        [Test]
        public void BloggerVersion2Test()
        {
            Tracing.TraceMsg("Entering BloggerVersion2Test");

            BloggerQuery query = new BloggerQuery();
            BloggerService service = new BloggerService(ApplicationName);

            string title = "V1" + Guid.NewGuid();

            service.ProtocolMajor = 1;

            service.RequestFactory = factory;
            query.Uri = new Uri(bloggerURI);

            // insert a new entry in version 1

            AtomEntry entry = ObjectModelHelper.CreateAtomEntry(1);
            entry.Categories.Clear();
            entry.Title.Text = title;
            entry.IsDraft = true;
            entry.ProtocolMajor = 12;


            AtomEntry returnedEntry = service.Insert(new Uri(bloggerURI), entry);
            Assert.IsTrue(returnedEntry.ProtocolMajor == service.ProtocolMajor);
            Assert.IsTrue(entry.IsDraft);
            Assert.IsTrue(returnedEntry.IsDraft);

            BloggerFeed feed = service.Query(query);
            Assert.IsTrue(feed.ProtocolMajor == service.ProtocolMajor);
            if (feed != null)
            {
                Assert.IsTrue(feed.TotalResults >= feed.Entries.Count, "totalresults should be >= number of entries");
                Assert.IsTrue(feed.Entries.Count > 0, "We should have some entries");
            }

            service.ProtocolMajor = 2;
            feed = service.Query(query);
            Assert.IsTrue(feed.ProtocolMajor == service.ProtocolMajor);

            if (feed != null)
            {
                Assert.IsTrue(feed.Entries.Count > 0, "We should have some entries");
                Assert.IsTrue(feed.TotalResults >= feed.Entries.Count, "totalresults should be >= number of entries");

                foreach (BloggerEntry e in feed.Entries)
                {
                    if (e.Title.Text == title)
                    {
                        Assert.IsTrue(e.ProtocolMajor == 2);
                        Assert.IsTrue(e.IsDraft);
                    }
                }
            }


        }

        /////////////////////////////////////////////////////////////////////////////

        //////////////////////////////////////////////////////////////////////
        /// <summary>checks for xhtml persistence</summary> 
        //////////////////////////////////////////////////////////////////////
        [Ignore("Currently broken on the server")]
        [Test]
        public void BloggerXHTMLTest()
        {
            Tracing.TraceMsg("Entering BloggerXHTMLTest");

            FeedQuery query = new FeedQuery();
            BloggerService service = new BloggerService(ApplicationName);

            if (bloggerURI != null)
            {
                if (userName != null)
                {
                    service.Credentials = new GDataCredentials(userName, passWord);
                }

                service.RequestFactory = factory;

                query.Uri = new Uri(bloggerURI);
                AtomFeed feed = service.Query(query);

                string strTitle = "Dinner time" + Guid.NewGuid();

                if (feed != null)
                {
                    // get the first entry
                    string xhtmlContent = "<div><b>this is an xhtml test text</b></div>";
                    AtomEntry entry = ObjectModelHelper.CreateAtomEntry(1);
                    entry.Categories.Clear();
                    entry.Title.Text = strTitle;
                    entry.Content.Type = "xhtml";
                    entry.Content.Content = xhtmlContent;

                    AtomEntry newEntry = feed.Insert(entry);
                    Tracing.TraceMsg("Created blogger entry");

                    // try to get just that guy.....
                    FeedQuery singleQuery = new FeedQuery();
                    singleQuery.Uri = new Uri(newEntry.SelfUri.ToString());
                    AtomFeed newFeed = service.Query(singleQuery);
                    AtomEntry sameGuy = newFeed.Entries[0];

                    Assert.IsTrue(sameGuy.Title.Text.Equals(newEntry.Title.Text), "both titles should be identical");
                    Assert.IsTrue(sameGuy.Content.Type.Equals("xhtml"));
                    Assert.IsTrue(sameGuy.Content.Content.Equals(xhtmlContent));

                }

                service.Credentials = null;
            }
        }

        //////////////////////////////////////////////////////////////////////
        /// <summary>runs an authentication test</summary> 
        //////////////////////////////////////////////////////////////////////
        [Test]
        public void GoogleAuthenticationTest()
        {
            Tracing.TraceMsg("Entering Blogger AuthenticationTest");

            BloggerQuery query = new BloggerQuery();
            BloggerService service = new BloggerService(ApplicationName);

            int iCount;

            if (bloggerURI != null)
            {
                if (userName != null)
                {
                    service.Credentials = new GDataCredentials(userName, passWord);
                }

                service.RequestFactory = factory;

                query.Uri = new Uri(bloggerURI);
                BloggerFeed blogFeed = service.Query(query);

                ObjectModelHelper.DumpAtomObject(blogFeed, CreateDumpFileName("AuthenticationTest"));
                iCount = blogFeed.Entries.Count;

                string strTitle = "Dinner time" + Guid.NewGuid();

                if (blogFeed != null && blogFeed.Entries.Count > 0)
                {
                    BloggerEntry entry = ObjectModelHelper.CreateAtomEntry(1) as BloggerEntry;
                    // blogger does not like labels yet.
                    entry.Categories.Clear();
                    entry.Title.Text = strTitle;
                    entry.Categories.Clear();
                    entry.IsDraft = true;
                    entry.Updated = Utilities.EmptyDate;
                    entry.Published = Utilities.EmptyDate;
                    BloggerEntry newEntry = blogFeed.Insert(entry);
                    iCount++;
                    Tracing.TraceMsg("Created blogger entry");

                    // try to get just that guy.....
                    BloggerQuery singleQuery = new BloggerQuery();
                    singleQuery.Uri = new Uri(newEntry.SelfUri.ToString());

                    BloggerFeed newFeed = service.Query(singleQuery);

                    BloggerEntry sameGuy = newFeed.Entries[0] as BloggerEntry;

                    Tracing.TraceMsg("retrieved blogger entry");

                    Assert.IsTrue(sameGuy.Title.Text.Equals(newEntry.Title.Text), "both titles should be identical");
                    Assert.IsTrue(sameGuy.IsDraft);

                }

                blogFeed = service.Query(query);

                Assert.AreEqual(iCount, blogFeed.Entries.Count,
                    "Feed should have one more entry, it has: " + blogFeed.Entries.Count);

                if (blogFeed != null && blogFeed.Entries.Count > 0)
                {
                    // look for the one with dinner time...
                    foreach (AtomEntry entry in blogFeed.Entries)
                    {
                        Tracing.TraceMsg("Entrie title: " + entry.Title.Text);
                        if (string.Compare(entry.Title.Text, strTitle) == 0)
                        {
                            entry.Content.Content = "Maybe stay until breakfast";
                            entry.Content.Type = "text";
                            entry.Update();
                            Tracing.TraceMsg("Updated entry");
                        }
                    }
                }

                blogFeed = service.Query(query);

                Assert.AreEqual(iCount, blogFeed.Entries.Count,
                    "Feed should have one more entry, it has: " + blogFeed.Entries.Count);

                if (blogFeed != null && blogFeed.Entries.Count > 0)
                {
                    // look for the one with dinner time...
                    foreach (AtomEntry entry in blogFeed.Entries)
                    {
                        Tracing.TraceMsg("Entrie title: " + entry.Title.Text);
                        if (string.Compare(entry.Title.Text, strTitle) == 0)
                        {
                            entry.Delete();
                            iCount--;
                            Tracing.TraceMsg("deleted entry");
                        }
                    }
                }


                blogFeed = service.Query(query);
                Assert.AreEqual(iCount, blogFeed.Entries.Count,
                    "Feed should have the same count again, it has: " + blogFeed.Entries.Count);

                service.Credentials = null;

            }

        }

        /////////////////////////////////////////////////////////////////////////////
    } /////////////////////////////////////////////////////////////////////////////
}