/***************************************************************************
 *  FeedsTableManager.cs
 *
 *  Copyright (C) 2007 Michael C. Urbanski
 *  Written by Mike Urbanski <michael.c.urbanski@gmail.com>
 ****************************************************************************/

/*  THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a
 *  copy of this software and associated documentation files (the "Software"),
 *  to deal in the Software without restriction, including without limitation
 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *  and/or sell copies of the Software, and to permit persons to whom the
 *  Software is furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 *  DEALINGS IN THE SOFTWARE.
 */

using System;
using System.Data;

using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace Migo.Syndication.Data
{
    /*class FeedsTableManager
    {
        public static readonly string initQuery = @"
            CREATE TABLE IF NOT EXISTS feeds (
            	'local_id' INTEGER  PRIMARY KEY,
            	'copyright' TEXT NOT NULL DEFAULT '',
            	'description' TEXT NOT NULL DEFAULT '',
            	'download_enclosures_automatically' INTEGER NOT NULL DEFAULT '0',
            	'download_url' TEXT NOT NULL DEFAULT '',
            	'image' TEXT NOT NULL DEFAULT '',
            	'interval' INTEGER NOT NULL DEFAULT '1440',
            	'is_list' INTEGER NOT NULL DEFAULT '0',
            	'language' TEXT NOT NULL DEFAULT '',
            	'last_build_date' DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00',
            	'last_download_error' INTEGER NOT NULL DEFAULT '0',
            	'last_download_time' DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00',
            	'last_write_time' DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00',
            	'link' TEXT NOT NULL DEFAULT '',
            	'local_enclosure_path' TEXT NOT NULL DEFAULT '',
            	'max_item_count' INTEGER NOT NULL DEFAULT '200',
            	'name' TEXT NOT NULL DEFAULT '',
            	'pubdate' DATETIME NOT NULL DEFAULT '0001-01-01 00:00:00',
            	'sync_setting' INTEGER NOT NULL DEFAULT '0',
            	'title' TEXT NOT NULL DEFAULT '',
            	'ttl' INTEGER NOT NULL DEFAULT '0',
            	'url' TEXT NOT NULL DEFAULT ''
            );

            CREATE TRIGGER IF NOT EXISTS feed_deleted_trigger
               AFTER DELETE ON feeds
            BEGIN
                DELETE FROM items WHERE parent_id=old.local_id;
            END;

            CREATE INDEX IF NOT EXISTS feeds_local_id_index ON feeds(local_id);";

        private static readonly string deleteFromFeedsBaseQuery = "DELETE FROM feeds WHERE";
        private static readonly string insertIntoFeedsQuery =
            String.Format (
                @"INSERT INTO feeds VALUES (
                    NULL, {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10},
                    {11}, {12}, {13}, {14}, {15}, {16}, {17}, {18}, {19}, {20}
                ); {21}",
                DbDefines.FeedsTableColumns.CopyrightParameter, DbDefines.FeedsTableColumns.DescriptionParameter,
                DbDefines.FeedsTableColumns.DownloadEnclosuresAutomaticallyParameter,
                DbDefines.FeedsTableColumns.DownloadUrlParameter, DbDefines.FeedsTableColumns.ImageParameter,
                DbDefines.FeedsTableColumns.IntervalParameter, DbDefines.FeedsTableColumns.IsListParameter,
                DbDefines.FeedsTableColumns.LanguageParameter, DbDefines.FeedsTableColumns.LastBuildDateParameter,
                DbDefines.FeedsTableColumns.LastDownloadErrorParameter, DbDefines.FeedsTableColumns.LastDownloadTimeParameter,
                DbDefines.FeedsTableColumns.LastWriteTimeParameter, DbDefines.FeedsTableColumns.LinkParameter,
                DbDefines.FeedsTableColumns.LocalEnclosurePathParameter, DbDefines.FeedsTableColumns.MaxItemCountParameter,
                DbDefines.FeedsTableColumns.NameParameter, DbDefines.FeedsTableColumns.PubDateParameter,
                DbDefines.FeedsTableColumns.SyncSettingParameter, DbDefines.FeedsTableColumns.TitleParameter,
                DbDefines.FeedsTableColumns.TtlParameter, DbDefines.FeedsTableColumns.UrlParameter,
                DbDefines.LastInsertIDQuery
            );

        private static readonly string selectAllFeedsQuery = "SELECT * FROM feeds;";
        private static readonly string selectAllFeedItemsQuery = "SELECT * FROM items;";
        private static readonly string selectAllFeedEnclosuresQuery = "SELECT * FROM enclosures;";

        private static readonly string updateFeedQuery =
            String.Format (
                @"UPDATE feeds SET
                    {2}={3}, {4}={5}, {6}={7}, {8}={9}, {10}={11}, {12}={13}, {14}={15}, {16}={17},
                    {18}={19}, {20}={21}, {22}={23}, {24}={25}, {26}={27}, {28}={29}, {30}={31},
                    {32}={33}, {34}={35}, {36}={37}, {38}={39}, {40}={41}, {42}={43}
                    WHERE {0}={1};",
                    DbDefines.FeedsTableColumns.LocalID, DbDefines.FeedsTableColumns.LocalIDParameter,
                    DbDefines.FeedsTableColumns.Copyright, DbDefines.FeedsTableColumns.CopyrightParameter,
                    DbDefines.FeedsTableColumns.Description, DbDefines.FeedsTableColumns.DescriptionParameter,
                    DbDefines.FeedsTableColumns.DownloadEnclosuresAutomatically,
                    DbDefines.FeedsTableColumns.DownloadEnclosuresAutomaticallyParameter,
                    DbDefines.FeedsTableColumns.DownloadUrl, DbDefines.FeedsTableColumns.DownloadUrlParameter,
                    DbDefines.FeedsTableColumns.Image, DbDefines.FeedsTableColumns.ImageParameter,
                    DbDefines.FeedsTableColumns.Interval, DbDefines.FeedsTableColumns.IntervalParameter,
                    DbDefines.FeedsTableColumns.IsList, DbDefines.FeedsTableColumns.IsListParameter,
                    DbDefines.FeedsTableColumns.Language, DbDefines.FeedsTableColumns.LanguageParameter,
                    DbDefines.FeedsTableColumns.LastBuildDate, DbDefines.FeedsTableColumns.LastBuildDateParameter,
                    DbDefines.FeedsTableColumns.LastDownloadError, DbDefines.FeedsTableColumns.LastDownloadErrorParameter,
                    DbDefines.FeedsTableColumns.LastDownloadTime, DbDefines.FeedsTableColumns.LastDownloadTimeParameter,
                    DbDefines.FeedsTableColumns.LastWriteTime, DbDefines.FeedsTableColumns.LastWriteTimeParameter,
                    DbDefines.FeedsTableColumns.Link, DbDefines.FeedsTableColumns.LinkParameter,
                    DbDefines.FeedsTableColumns.LocalEnclosurePath, DbDefines.FeedsTableColumns.LocalEnclosurePathParameter,
                    DbDefines.FeedsTableColumns.MaxItemCount, DbDefines.FeedsTableColumns.MaxItemCountParameter,
                    DbDefines.FeedsTableColumns.Name, DbDefines.FeedsTableColumns.NameParameter,
                    DbDefines.FeedsTableColumns.PubDate, DbDefines.FeedsTableColumns.PubDateParameter,
                    DbDefines.FeedsTableColumns.SyncSetting, DbDefines.FeedsTableColumns.SyncSettingParameter,
                    DbDefines.FeedsTableColumns.Title, DbDefines.FeedsTableColumns.TitleParameter,
                    DbDefines.FeedsTableColumns.Ttl, DbDefines.FeedsTableColumns.TtlParameter,
                    DbDefines.FeedsTableColumns.Url, DbDefines.FeedsTableColumns.UrlParameter
            );


        public static bool Commit (IEnumerable<Feed> feeds)
        {
            if (feeds == null) {
                throw new ArgumentNullException ("feeds");
            }

            bool ret = false;

            try {
                foreach (Feed f in feeds) {
                    f.Commit ();
                }

                ret = true;
            } catch {}

            return ret;
        }

        public static List<Feed> GetAllFeeds (FeedsManager manager)
        {
            if (manager == null) {
                throw new ArgumentNullException ("manager");
            }

            DateTime start = DateTime.Now;
            Console.WriteLine (start);

            List<Feed> feeds;
            Dictionary<long,ICollection<FeedItem>> feedItems;
            Dictionary<long,FeedEnclosure> feedEnclosures;

            feedEnclosures = BuildEnclosuresDict ();
            feedItems = BuildItemsDict (feedEnclosures);
            feeds = BuildFeedsList (manager, feedItems);

            feedItems.Clear ();
            feedEnclosures.Clear ();

            Console.WriteLine (DateTime.Now - start);
            return feeds;
        }

        public static void Delete (Feed feed)
        {
            if (feed == null) {
                throw new ArgumentNullException ("feed");
            }

            DatabaseManager.ExecuteNonQuery (
                String.Format (
                    "{0} {1}={2};",
                    deleteFromFeedsBaseQuery,
                    DbDefines.FeedsTableColumns.LocalID,
                    DbDefines.FeedsTableColumns.LocalIDParameter
                ),
                DbDefines.FeedsTableColumns.LocalID,
                feed.LocalID.ToString ()
            );
        }

        public static void Delete (IEnumerable<Feed> feeds)
        {
            if (feeds == null) {
            	throw new ArgumentNullException ("feeds");
            }

            List<long> ids = new List<long> ();

            foreach (Feed f in feeds) {
                if (f != null) {
                    ids.Add (f.LocalID);
                }
            }

            if (ids.Count > 0) {
                string query = DataUtility.MultipleOnIDQuery (
                    deleteFromFeedsBaseQuery, DbDefines.FeedsTableColumns.LocalID, ids.ToArray ()
                );

                DatabaseManager.ExecuteNonQuery (query);
            }
        }

        public static void Init ()
        {
            DatabaseManager.ExecuteNonQuery (initQuery);
        }

        public static long Insert (Feed feed)
        {
            if (feed == null) {
                throw new ArgumentNullException ("feed");
            } else if (feed.LocalID > 0) {
                return feed.LocalID;
            }

            long ret = -1;

            try {
                ret = Convert.ToInt64 (
                    DatabaseManager.ExecuteScalar (
                        insertIntoFeedsQuery,
                        DbDefines.FeedsTableColumns.Copyright, feed.Copyright == null ? String.Empty : feed.Copyright,
                        DbDefines.FeedsTableColumns.Description, feed.Description == null ? String.Empty : feed.Description,
                        DbDefines.FeedsTableColumns.DownloadEnclosuresAutomatically.ToString (),
                        feed.DownloadEnclosuresAutomatically.ToString (),
                        DbDefines.FeedsTableColumns.DownloadUrl, feed.DownloadUrl == null ? String.Empty : feed.DownloadUrl,
                        DbDefines.FeedsTableColumns.Image, feed.Image == null ? String.Empty : feed.Image,
                        DbDefines.FeedsTableColumns.Interval, feed.Interval.ToString (),
                        DbDefines.FeedsTableColumns.IsList, feed.IsList.ToString (),
                        DbDefines.FeedsTableColumns.Language, feed.Language == null ? String.Empty : feed.Language,
                        DbDefines.FeedsTableColumns.LastBuildDate, feed.LastBuildDate.ToUniversalTime ().ToString ("u"),
                        DbDefines.FeedsTableColumns.LastDownloadError, ((int)feed.LastDownloadError).ToString (),
                        DbDefines.FeedsTableColumns.LastDownloadTime, feed.LastDownloadTime.ToUniversalTime ().ToString ("u"),
                        DbDefines.FeedsTableColumns.LastWriteTime, feed.LastWriteTime.ToUniversalTime ().ToString ("u"),
                        DbDefines.FeedsTableColumns.Link, feed.Link == null ? String.Empty : feed.Link,
                        DbDefines.FeedsTableColumns.LocalEnclosurePath, feed.LocalEnclosurePath == null ? String.Empty : feed.LocalEnclosurePath,
                        DbDefines.FeedsTableColumns.MaxItemCount, feed.MaxItemCount.ToString (),
                        DbDefines.FeedsTableColumns.Name, feed.Name == null ? String.Empty : feed.Name,
                        DbDefines.FeedsTableColumns.PubDate, feed.PubDate.ToUniversalTime ().ToString ("u"),
                        DbDefines.FeedsTableColumns.SyncSetting, ((int)feed.SyncSetting).ToString (),
                        DbDefines.FeedsTableColumns.Title, feed.Title == null ? String.Empty : feed.Title,
                        DbDefines.FeedsTableColumns.Ttl, feed.Ttl.ToString (),
                        DbDefines.FeedsTableColumns.Url, feed.Url == null ? String.Empty : feed.Url
                    )
                );
            } catch {}

            Console.WriteLine ("feed.LocalID:  {0}", ret);

            return ret;
        }

        public static bool Insert (IEnumerable<Feed> feeds)
        {
            if (feeds == null) {
                throw new ArgumentNullException ("feeds");
            }

            bool ret = false;

            try {
                foreach (Feed f in feeds) {
                    Insert (f);
                }

                ret = true;
            } catch {}

            return ret;
        }

        public static void Update (Feed feed)
        {
            if (feed == null) {
                throw new ArgumentNullException ("feed");
            }

            DatabaseManager.ExecuteNonQuery (
                updateFeedQuery,
                DbDefines.FeedsTableColumns.LocalID, feed.LocalID.ToString (),
                DbDefines.FeedsTableColumns.Copyright, feed.Copyright == null ? String.Empty : feed.Copyright,
                DbDefines.FeedsTableColumns.Description, feed.Description == null ? String.Empty : feed.Description,
                DbDefines.FeedsTableColumns.DownloadEnclosuresAutomatically.ToString (),
                feed.DownloadEnclosuresAutomatically.ToString (),
                DbDefines.FeedsTableColumns.DownloadUrl, feed.DownloadUrl == null ? String.Empty : feed.DownloadUrl,
                DbDefines.FeedsTableColumns.Image, feed.Image == null ? String.Empty : feed.Image,
                DbDefines.FeedsTableColumns.Interval, feed.Interval.ToString (),
                DbDefines.FeedsTableColumns.IsList, feed.IsList.ToString (),
                DbDefines.FeedsTableColumns.Language, feed.Language == null ? String.Empty : feed.Language,
                DbDefines.FeedsTableColumns.LastBuildDate, feed.LastBuildDate.ToUniversalTime ().ToString ("u"),
                DbDefines.FeedsTableColumns.LastDownloadError, ((int)feed.LastDownloadError).ToString (),
                DbDefines.FeedsTableColumns.LastDownloadTime, feed.LastDownloadTime.ToUniversalTime ().ToString ("u"),
                DbDefines.FeedsTableColumns.LastWriteTime, feed.LastWriteTime.ToUniversalTime ().ToString ("u"),
                DbDefines.FeedsTableColumns.Link, feed.Link == null ? String.Empty : feed.Link,
                DbDefines.FeedsTableColumns.LocalEnclosurePath, feed.LocalEnclosurePath == null ? String.Empty : feed.LocalEnclosurePath,
                DbDefines.FeedsTableColumns.MaxItemCount, feed.MaxItemCount.ToString (),
                DbDefines.FeedsTableColumns.Name, feed.Name == null ? String.Empty : feed.Name,
                DbDefines.FeedsTableColumns.PubDate, feed.PubDate.ToUniversalTime ().ToString ("u"),
                DbDefines.FeedsTableColumns.SyncSetting, ((int)feed.SyncSetting).ToString (),
                DbDefines.FeedsTableColumns.Title, feed.Title == null ? String.Empty : feed.Title,
                DbDefines.FeedsTableColumns.Ttl, feed.Ttl.ToString (),
                DbDefines.FeedsTableColumns.Url, feed.Url == null ? String.Empty : feed.Url
            );
        }

        public static bool Update (IEnumerable<Feed> feeds)
        {
            if (feeds == null) {
                throw new ArgumentNullException ("feeds");
            }

            bool ret = false;

            try {
                foreach (Feed f in feeds) {
                    Update (f);
                    ret = true;
                }
            } catch {}

            return ret;
        }

        private static Dictionary<long,FeedEnclosure> BuildEnclosuresDict ()
        {
            IDataReader reader = null;
            Dictionary<long,FeedEnclosure> ret =
                new Dictionary<long,FeedEnclosure> ();

            try {
                FeedEnclosure tmpFE;
                reader = DatabaseManager.ExecuteReader (selectAllFeedEnclosuresQuery);
                FeedEnclosureDataWrapper fedw = new FeedEnclosureDataWrapper (reader);

                while (fedw.Read ()) {
                    tmpFE = new FeedEnclosure (fedw);
                    ret.Add (fedw.ParentID, tmpFE);
                }
            } finally {
                if (reader != null) {
                    reader.Dispose ();
                    reader = null;
                }
            }

            return ret;
        }

        private static Dictionary<long,ICollection<FeedItem>>
            BuildItemsDict (Dictionary<long,FeedEnclosure> feedEnclosures)
        {
            IDataReader reader = null;
            Dictionary<long,ICollection<FeedItem>> ret =
                new Dictionary<long,ICollection<FeedItem>> ();

            try {
                FeedItem tmpItem;

                DateTime start = DateTime.Now;
                reader = DatabaseManager.ExecuteReader (selectAllFeedItemsQuery);
                Console.WriteLine ("Time to select all feed items:  {0}", DateTime.Now-start);

                FeedItemDataWrapper fidw = new FeedItemDataWrapper (reader);

                while (fidw.Read ()) {
                    tmpItem = new FeedItem (fidw);

                    if (!ret.ContainsKey (fidw.ParentID)) {
                        ret.Add (fidw.ParentID, new List<FeedItem> ());
                    }

                    ret[fidw.ParentID].Add (tmpItem);

                    if (feedEnclosures.ContainsKey (tmpItem.LocalID)) {
                        tmpItem.Enclosure = feedEnclosures[tmpItem.LocalID];
                    }
                }
            } finally {
                if (reader != null) {
                    reader.Dispose ();
                    reader = null;
                }
            }

            return ret;
        }

        private static List<Feed> BuildFeedsList (FeedsManager manager, Dictionary<long,ICollection<FeedItem>> feedItems)
        {
            IDataReader reader = null;
            List<Feed> ret = new List<Feed> ();

            try {
                Feed tmpFeed;
                ICollection<FeedItem> tmpCollection;

                reader = DatabaseManager.ExecuteReader (selectAllFeedsQuery);
                FeedDataWrapper fdw = new FeedDataWrapper (reader);

                while (fdw.Read ()) {
                    tmpFeed = new Feed (manager, fdw);

                    if (feedItems.TryGetValue (tmpFeed.LocalID, out tmpCollection)) {
                        tmpFeed.SetItems (tmpCollection);
                    }

                    ret.Add (tmpFeed);
                }
            } finally {
                if (reader != null) {
                    reader.Dispose ();
                    reader = null;
                }
            }

            return ret;
        }
    }*/
}
