using Mall.DataAccess.Utils;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;

namespace Mall.DataAccess
{
    /// <summary>
    /// 数据库连接事务的Session对象
    /// </summary>
    public class DBSessionBase : IDBSession
    {
        private IDbConnection _connection;
        private IDbTransaction _transaction;
        private readonly DataBaseType _dbType;
        private readonly string _connKey;
        private bool _isDisposed = false;

        /// <summary>
        /// 数据库类型枚举
        /// </summary>
        public DataBaseType DbType
        {
            get { return _dbType; }
        }

        /// <summary>
        /// 连接字符串
        /// </summary>
        public string ConnKey
        {
            get { return _connKey; }
        }

        /// <summary>
        /// 数据库连接对象
        /// </summary>
        public IDbConnection Connection
        {
            get { return _connection; }
        }

        /// <summary>
        /// 数据库事务对象
        /// </summary>
        public IDbTransaction Transaction
        {
            get { return _transaction; }
            set { _transaction = value; }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="Database">数据库对象</param>
        public DBSessionBase(IDatabase Database)
        {
            _connection = Database.Connection;
            _dbType = Database.DbType;
            _connKey = Database.ConnKey;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="connKey">连接字符串</param>
        public DBSessionBase(string connKey)
        {
            _dbType = DBUtils.GetDBTypeByConnKey(connKey);
            _connKey = connKey;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="connKey">连接字符串</param>
        /// <param name="Connection">连接对象</param>
        /// <param name="Transaction">事务对象</param>
        public DBSessionBase(string connKey, IDbConnection Connection, IDbTransaction Transaction)
        {
            _dbType = DBUtils.GetDBTypeByConnKey(connKey);
            _connKey = connKey;
            this._connection = Connection;
            this._transaction = Transaction;
        }

        /// <summary>
        /// 开启会话
        /// </summary>
        /// <param name="isolation"></param>
        /// <returns></returns>
        public IDbTransaction Begin(IsolationLevel isolation = IsolationLevel.ReadCommitted)
        {
            _connection.Open();
            _transaction = _connection.BeginTransaction(isolation);
            return _transaction;
        }

        /// <summary>
        /// 事务提交
        /// </summary>
        public void Commit()
        {
            _transaction.Commit();
            _transaction = null;
        }

        /// <summary>
        /// 提交事务
        /// </summary>
        /// <param name="methodName">方法名称</param>
        public void Commit(string methodName)
        {
            try
            {
                _transaction.Commit();
                _transaction = null;
            }
            catch(Exception ex)
            {
                WriteLog(ex, methodName);
            }
        }

        /// <summary>
        /// 事务回滚
        /// </summary>
        public void Rollback()
        {
            _transaction.Rollback();
            _transaction.Dispose();
        }

        /// <summary>
        /// 回滚事务扩展
        /// </summary>
        /// <param name="methodName">方法名称</param>
        public void Rollback(string methodName)
        {
            try
            {
                _transaction.Rollback();
                _transaction.Dispose();
            }
            catch (Exception ex)
            {
                WriteLog(ex, methodName);
            }
        }


        /// <summary>
        /// 写日志
        /// </summary>
        /// <param name="exception">异常信息</param>
        /// <param name="otherMsg">其他信息</param>
        private static void WriteLog(Exception exception, string otherMsg="")
        {
            string logPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "syslog");
            if (!Directory.Exists(logPath))
            {
                Directory.CreateDirectory(logPath);
            }
            string str = "";
            try
            {
                str += string.Format(@"
DateTime:{0}", DateTime.Now.ToString());
                if (exception != null)
                {
                    if (exception.InnerException != null)
                    {
                        exception = exception.InnerException;
                    }
                    str += string.Format(@"
Message:{0}
StackTrace:
{1}
Source:{2}
"
 , exception.Message
 , exception.StackTrace
 , exception.Source

                    );
                }
                str += string.Format(@"
ExtMessage:{0}", otherMsg);
                string filePath = "";
                object lockObj = new object();
                filePath = Path.Combine(logPath, DateTime.Now.ToString("yyyyMMdd") + ".txt");       
                lock (lockObj)
                {
                    StreamWriter sw = new StreamWriter(filePath, true);
                    sw.WriteLine(str);
                    sw.Close();
                }
            }
            catch
            {

            }
        }

        /// <summary>
        /// 析构函数
        /// </summary>
        ~DBSessionBase()
        {
            Dispose(false);//释放非托管资源
        }

        /// <summary>
        /// 资源释放
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {
            if (!_isDisposed)
            {
                if (_connection != null)
                {
                    using (_connection)
                    {
                        if (_connection.State != ConnectionState.Closed)
                        {
                            if (_transaction != null)
                            {
                                _transaction.Rollback();
                                _transaction.Dispose();
                            }
                        }
                        _connection.Close();
                        _connection.Dispose();
                    }
                }
                this._isDisposed = true;
            }
        }
    }
}