﻿using System;
using System.Threading.Tasks;
using Kaleidoscope.Extensions.EntityFrameworkCore.Context;
using Kaleidoscope.Extensions.EntityFrameworkCore.Entities;
using Kaleidoscope.Extensions.EntityFrameworkCore.Repositories;

namespace Kaleidoscope.Extensions.EntityFrameworkCore.Transactions
{
    /// <summary>
    /// Interface for Unit of Work
    /// </summary>
    public interface IUnitOfWork : IDisposable
    {
        #region Status

        /// <summary>
        /// Indicator for pending changes.
        /// </summary>
        bool HasPendingChanges { get; }

        #endregion

        #region Data Context
        
        IDataContext Context { get; }

        #endregion

        #region Repository

        /// <summary>
        /// Create a repository for the given entity type.
        /// </summary>
        /// <typeparam name="T">Entity Type</typeparam>
        /// <returns>Repository</returns>
        IRepository<T> CreateRepository<T>() where T : class, IEntity;

        /// <summary>
        /// Attach a repository to the unit of work.
        /// </summary>
        /// <param name="repository">Repository</param>
        /// <exception cref="InvalidOperationException">This exception will be thrown when the data context in the repository has pending changes.</exception>
        void AttachRepository<T>(IRepository<T> repository) where T : class, IEntity;

        #endregion

        #region Transaction

        /// <summary>
        /// Save all pending changes to the data context.
        /// </summary>
        /// <returns>number of changed entities</returns>
        int SaveChanges();

        /// <summary>
        /// Save all pending changes to the data context.
        /// </summary>
        /// <returns>number of changed entities</returns>
        Task<int> SaveChangesAsync();

        /// <summary>
        /// Revert all pending changes in the data context.
        /// </summary>
        /// <returns>number of reverted entities</returns>
        int RevertChanges();

        #endregion
    }
}