// Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System;
using System.Threading;
using System.Threading.Tasks;
using DotNetCore.CAP;
using MongoDB.Bson;
using MongoDB.Driver.Core.Bindings;

// ReSharper disable once CheckNamespace
namespace MongoDB.Driver
{
    internal class CapMongoDbClientSessionHandle : IClientSessionHandle
    {
        private readonly IClientSessionHandle _sessionHandle;
        private readonly ICapTransaction _transaction;

        public CapMongoDbClientSessionHandle(ICapTransaction transaction)
        {
            _transaction = transaction;
            _sessionHandle = (IClientSessionHandle)_transaction.DbTransaction;
        }

        public void Dispose()
        {
            _transaction.Dispose();
        }

        public void AbortTransaction(CancellationToken cancellationToken = default)
        {
            _transaction.Rollback();
        }

        public Task AbortTransactionAsync(CancellationToken cancellationToken = default)
        {
            _transaction.Rollback();
            return Task.CompletedTask;
        }

        public void AdvanceClusterTime(BsonDocument newClusterTime)
        {
            _sessionHandle.AdvanceClusterTime(newClusterTime);
        }

        public void AdvanceOperationTime(BsonTimestamp newOperationTime)
        {
            _sessionHandle.AdvanceOperationTime(newOperationTime);
        }

        public void CommitTransaction(CancellationToken cancellationToken = default)
        {
            _transaction.Commit();
        }

        public Task CommitTransactionAsync(CancellationToken cancellationToken = default)
        {
            _transaction.Commit();
            return Task.CompletedTask;
        }

        public void StartTransaction(TransactionOptions transactionOptions = null)
        {
            _sessionHandle.StartTransaction(transactionOptions);
        }

        public IMongoClient Client => _sessionHandle.Client;
        public BsonDocument ClusterTime => _sessionHandle.ClusterTime;
        public bool IsImplicit => _sessionHandle.IsImplicit;
        public bool IsInTransaction => _sessionHandle.IsInTransaction;
        public BsonTimestamp OperationTime => _sessionHandle.OperationTime;
        public ClientSessionOptions Options => _sessionHandle.Options;
        public IServerSession ServerSession => _sessionHandle.ServerSession;
        public ICoreSessionHandle WrappedCoreSession => _sessionHandle.WrappedCoreSession;

        public IClientSessionHandle Fork()
        {
            return _sessionHandle.Fork();
        }

        public TResult WithTransaction<TResult>(Func<IClientSessionHandle, CancellationToken, TResult> callback, TransactionOptions transactionOptions = null, CancellationToken cancellationToken = default)
        {
            return _sessionHandle.WithTransaction(callback, transactionOptions, cancellationToken);
        }

        public Task<TResult> WithTransactionAsync<TResult>(Func<IClientSessionHandle, CancellationToken, Task<TResult>> callbackAsync, TransactionOptions transactionOptions = null, CancellationToken cancellationToken = default)
        {
            return _sessionHandle.WithTransactionAsync(callbackAsync, transactionOptions, cancellationToken);
        }
    }
}