//-----------------------------------------------------------------------
// 
//     Copyright (c) Microsoft Corporation.
// 
//-----------------------------------------------------------------------
namespace Microsoft.Isam.Esent.Interop
{
    using System;
    using System.Globalization;
    /// 
    /// A class that encapsulates an update on a JET_TABLEID.
    /// 
    public class Update : EsentResource
    {
        /// 
        /// The underlying JET_SESID.
        /// 
        private readonly JET_SESID sesid;
        /// 
        /// The underlying JET_TABLEID.
        /// 
        private readonly JET_TABLEID tableid;
        /// 
        /// The type of update.
        /// 
        private readonly JET_prep prep;
        /// 
        /// Initializes a new instance of the Update class. This automatically
        /// begins an update. The update will be cancelled if
        /// not explicitly saved.
        /// 
        /// The session to start the transaction for.
        /// The tableid to prepare the update for.
        /// The type of update.
        public Update(JET_SESID sesid, JET_TABLEID tableid, JET_prep prep)
        {
            if (JET_prep.Cancel == prep)
            {
                throw new ArgumentException("Cannot create an Update for JET_prep.Cancel", "prep");
            }
            this.sesid = sesid;
            this.tableid = tableid;
            this.prep = prep;
            Api.JetPrepareUpdate(this.sesid, this.tableid, this.prep);
            this.ResourceWasAllocated();
        }
        /// 
        /// Returns a  that represents the current .
        /// 
        /// 
        /// A  that represents the current .
        /// 
        public override string ToString()
        {
            return string.Format(CultureInfo.InvariantCulture, "Update ({0})", this.prep);
        }
        /// 
        /// Update the tableid.
        /// 
        /// Returns the bookmark of the updated record. This can be null.
        /// The size of the bookmark buffer.
        /// Returns the actual size of the bookmark.
        /// 
        /// Save is the final step in performing an insert or an update. The update is begun by
        /// calling creating an Update object and then by calling JetSetColumn or JetSetColumns one or more times
        /// to set the record state. Finally, Update is called to complete the update operation.
        /// Indexes are updated only by Update or and not during JetSetColumn or JetSetColumns.
        /// 
        public void Save(byte[] bookmark, int bookmarkSize, out int actualBookmarkSize)
        {
            this.CheckObjectIsNotDisposed();
            if (!this.HasResource)
            {
                throw new InvalidOperationException("Not in an update");
            }
            Api.JetUpdate(this.sesid, this.tableid, bookmark, bookmarkSize, out actualBookmarkSize);
            this.ResourceWasReleased();
        }
        /// 
        /// Update the tableid.
        /// 
        /// 
        /// Save is the final step in performing an insert or an update. The update is begun by
        /// calling creating an Update object and then by calling JetSetColumn or JetSetColumns one or more times
        /// to set the record state. Finally, Update is called to complete the update operation.
        /// Indexes are updated only by Update or and not during JetSetColumn or JetSetColumns.
        /// 
        public void Save()
        {
            int ignored;
            this.Save(null, 0, out ignored);
        }
        /// 
        /// Update the tableid and position the tableid on the record that was modified.
        /// This can be useful when inserting a record because by default the tableid
        /// remains in its old location.
        /// 
        /// 
        /// Save is the final step in performing an insert or an update. The update is begun by
        /// calling creating an Update object and then by calling JetSetColumn or JetSetColumns one or more times
        /// to set the record state. Finally, Update is called to complete the update operation.
        /// Indexes are updated only by Update or and not during JetSetColumn or JetSetColumns.
        /// 
        public void SaveAndGotoBookmark()
        {
            byte[] bookmark = null;
            try
            {
                bookmark = Caches.BookmarkCache.Allocate();
                int actualBookmarkSize;
                this.Save(bookmark, bookmark.Length, out actualBookmarkSize);
                Api.JetGotoBookmark(this.sesid, this.tableid, bookmark, actualBookmarkSize);
            }
            finally
            {
                if (bookmark != null)
                {
                    Caches.BookmarkCache.Free(ref bookmark);
                }
            }
        }
        /// 
        /// Cancel the update.
        /// 
        public void Cancel()
        {
            this.CheckObjectIsNotDisposed();
            if (!this.HasResource)
            {
                throw new InvalidOperationException("Not in an update");
            }
            Api.JetPrepareUpdate(this.sesid, this.tableid, JET_prep.Cancel);
            this.ResourceWasReleased();
        }
        /// 
        /// Called when the transaction is being disposed while active.
        /// This should rollback the transaction.
        /// 
        protected override void ReleaseResource()
        {
            this.Cancel();
        }
    }
}