using System;
using System.Threading;

namespace BulkPrinting
{
    public class LogDownloader : ThreadHelper
    {
        private const int _vendorEventPageSize = 5000;
        private const int _retryInterval = 30000;

        private DBHelper _db;

        public LogDownloader(DBHelper db)
        {
            _db = db;
        }

        protected override void Run()
        {
            bool isCancelled = false;
            int maxRemoteId = Utility.GetSavedParameterAsInt(_db, "SyncBackwardsFromLogId");
            while (!isCancelled && (maxRemoteId > 0))
            {
                var EventPage = new Page<VendorEvent>();
                if (Utility.RESTRequest(ref EventPage, String.Format(
                    "/api/vendorevents/?maxRemoteId={0}&pageSize={1}", maxRemoteId, _vendorEventPageSize)))
                {
                    lock (_db.WriteLock)
                    {
                        using (var trans = _db.BeginTransaction())
                        {
                            using (var insertCommand = _db.CreateCommand(
                                "INSERT INTO Logs (Id,  UserId,  VoucherId,  EventDate,  EventType,  Retry,  Summarised) " +
                                          "VALUES (@id, @userid, @voucherid, @eventdate, @eventtype, @retry, 0)",
                                trans))
                            using (var updateCommand = _db.CreateCommand(
                                "UPDATE Parameters SET Value=@Value WHERE Key='SyncBackwardsFromLogId'", trans))
                            {
                                foreach (VendorEvent Event in EventPage.Items)
                                {
                                    if (!Event.RemoteId.HasValue)
                                    {
                                        throw new Exception("Downloaded event with no remote ID");
                                    }
                                    else if (Event.RemoteId.Value > maxRemoteId)
                                    {
                                        throw new Exception("Downloaded event remote ID was not in descending order");
                                    }

                                    insertCommand.Parameters.Clear();
                                    insertCommand.Parameters.AddWithValue("@id", Event.RemoteId);
                                    insertCommand.Parameters.AddWithValue("@userid", Event.UserId);
                                    insertCommand.Parameters.AddWithValue("@voucherid", Event.VoucherId);
                                    insertCommand.Parameters.AddWithValue("@eventdate", Event.EventDate.UtcDateTime);
                                    insertCommand.Parameters.AddWithValue("@eventtype", Event.EventType);
                                    insertCommand.Parameters.AddWithValue("@retry", Event.Retry);
                                    insertCommand.ExecuteNonQuery();

                                    maxRemoteId = Event.RemoteId.Value - 1;
                                }

                                updateCommand.Parameters.Clear();
                                updateCommand.Parameters.AddWithValue("@Value", maxRemoteId.ToString());
                                updateCommand.ExecuteNonQuery();
                            }

                            trans.Commit();
                        }
                    }

                    lock (_lock)
                    {
                        isCancelled = _cancelled;
                    }
                }
                else
                {
                    lock (_lock)
                    {
                        if (!_cancelled)
                        {
                            Monitor.Wait(_lock, _retryInterval);
                        }
                        isCancelled = _cancelled;
                    }
                }
            }
        }
    }
}
