using System;
using System.Text;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;

using Dapper;
using DapperExtensions;
using DapperExtensions.Mapper;
using DapperExtensions.Sql;
using DapperExtensions.ValueObject;
using Mall.DataAccess;
using System.Configuration;
using Mall.DataAccess.Utils;

namespace DapperExtensions.Lambda
{

    /// <summary>
    /// LambdaUpdate泛型帮助类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class LambdaUpdateHelper<T> : LambdaUpdateHelper where T : class
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="connection">数据库连接对象</param>
        /// <param name="transaction">事务对象</param>
        /// <param name="classMap">数据库配置接口对象</param>
        /// <param name="commandTimeout">超时时间</param>
        public LambdaUpdateHelper(IDbConnection connection, IDbTransaction transaction, IClassMapper classMap, int? commandTimeout = null)
            : base(connection, transaction, classMap, commandTimeout)
        {
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="connKey">l连接字符串Key</param>
        /// <param name="classMap">数据库配置接口对象</param>
        /// <param name="commandTimeout">超时时间</param>
        public LambdaUpdateHelper(string connKey, IClassMapper classMap, int? commandTimeout = null)
            : base(connKey, classMap, commandTimeout)
        {
        }

        #region Sql组装  Set   Where ……

        /// <summary>
        /// Set
        /// </summary>
        /// <param name="set">WHERE接口</param>
        /// <returns></returns>
        public LambdaUpdateHelper<T> Set(IWhere set)
        {
            return (LambdaUpdateHelper<T>)base.Set(set.ToWhereClip());
        }

        /// <summary>
        /// Set
        /// </summary>
        /// <param name="set">WHERE接口</param>
        /// <returns></returns>
        public LambdaUpdateHelper<T> Set(IWhere<T> set)
        {
            return (LambdaUpdateHelper<T>)base.Set(set.ToWhereClip());
        }

        /// <summary>
        /// Set
        /// </summary>
        /// <param name="lambdaSet">表达式</param>
        /// <returns></returns>
        public LambdaUpdateHelper<T> Set(Expression<Func<T, bool>> lambdaSet)
        {
            return (LambdaUpdateHelper<T>)Set(ExpressionToClip<T>.ToWhereClip(lambdaSet));
        }


        /// <summary>
        /// 新增WHERE条件
        /// </summary>
        /// <param name="where">WHERE接口</param>
        /// <returns></returns>
        public LambdaUpdateHelper<T> Where(IWhere where)
        {
            return (LambdaUpdateHelper<T>)base.Where(where.ToWhereClip());
        }

        /// <summary>
        ///  新增WHERE条件
        /// </summary>
        /// <param name="where">WHERE接口</param>
        /// <returns></returns>
        public LambdaUpdateHelper<T> Where(IWhere<T> where)
        {
            return (LambdaUpdateHelper<T>)base.Where(where.ToWhereClip());
        }

        /// <summary>
        /// 新增WHERE条件
        /// </summary>
        /// <param name="lambdaWhere">表达式</param>
        /// <returns></returns>
        public LambdaUpdateHelper<T> Where(Expression<Func<T, bool>> lambdaWhere)
        {
            return (LambdaUpdateHelper<T>)Where(ExpressionToClip<T>.ToWhereClip(lambdaWhere));
        }
        #endregion
    }


    /// <summary>
    /// LambdaUpdate帮助类
    /// </summary>
    public class LambdaUpdateHelper
    {
        #region 属性 变量

        /// <summary>
        /// 数据库配置接口对象
        /// </summary>
        public IClassMapper ClassMap { get; private set; }
        
        /// <summary>
        /// 连接对象
        /// </summary>
        public IDbConnection Connection { get; private set; }

        /// <summary>
        /// 连接字符串Key
        /// </summary>
        public string ConnKey { get; private set; }

        /// <summary>
        /// 事务对象
        /// </summary>
        public IDbTransaction Transaction { get; private set; }
        
        /// <summary>
        /// 数据库类型枚举
        /// </summary>
        public DataBaseType DbType { get; private set; }

        /// <summary>
        /// 超时时间
        /// </summary>
        [DefaultValue(30000)]
        public int CommandTimeout { get; private set; }

        /// <summary>
        /// 是都使用NoLOCK
        /// </summary>
        [DefaultValue(false)]
        public bool EnabledNoLock { get; private set; }

        private string _SqlString = string.Empty;
        private WhereClip _WhereClip = WhereClip.All;
        private WhereClip _SetClip = WhereClip.All;



        private Dictionary<string, KeyValuePair<string, WhereClip>> _Joins = new Dictionary<string, KeyValuePair<string, WhereClip>>();
        private Dictionary<string, Parameter> _Parameters = new Dictionary<string, Parameter>();

        /// <summary>
        /// Where条件
        /// </summary>
        public WhereClip SetClip
        {
            get { return _SetClip; }
            private set { _SetClip = value; }
        }

        /// <summary>
        /// Where条件
        /// </summary>
        public WhereClip WhereClip
        {
            get { return _WhereClip; }
            private set { _WhereClip = value; }
        }

        /// <summary>
        /// 连接字典
        /// </summary>
        public Dictionary<string, KeyValuePair<string, WhereClip>> Joins
        {
            get { return _Joins; }
            private set { _Joins = value; }
        }

        /// <summary>
        /// 参数字典
        /// </summary>
        public Dictionary<string, Parameter> Parameters
        {
            get
            {
                if (null == _Parameters || _Parameters.Count == 0)
                {
                    if (!WhereClip.IsNullOrEmpty(_SetClip))
                    {
                        foreach (var item in _SetClip.Parameters)
                        {
                            _Parameters.Add(item.ParameterName, item);
                        }
                    }
                    if (!WhereClip.IsNullOrEmpty(_WhereClip))
                    {
                        foreach (var item in _WhereClip.Parameters)
                        {
                            _Parameters.Add(item.ParameterName, item);
                        }
                    }
                }
                return _Parameters;
            }
            internal set
            {
                this._Parameters = value;
            }
        }

        #endregion

        #region 构造函数

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="connection">连接对象</param>
        /// <param name="transaction">事务对象</param>
        /// <param name="classMap">数据库配置接口对象</param>
        /// <param name="commandTimeout">超时时间</param>
        public LambdaUpdateHelper(IDbConnection connection, IDbTransaction transaction, IClassMapper classMap, int? commandTimeout = null)
        {
            this.Connection = connection;
            this.DbType = DapperExtension.DapperImplementor.DbType;
            this.Transaction = transaction;
            this.ClassMap = classMap;
            if (null != commandTimeout)
            {
                this.CommandTimeout = CommandTimeout;
            }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="connKey">连接Key</param>
        /// <param name="classMap">数据库配置接口对象</param>
        /// <param name="commandTimeout">超时时间</param>
        public LambdaUpdateHelper(string connKey, IClassMapper classMap, int? commandTimeout = null)
        {
            this.ConnKey = connKey;
            this.DbType = DBUtils.GetDBTypeByConnKey(connKey);
            this.ClassMap = classMap;
            if (null != commandTimeout)
            {
                this.CommandTimeout = CommandTimeout;
            }
        }
        #endregion

        #region Sql组装  Select  OrderBy  Group ……

        /// <summary>
        /// 添加Where条件
        /// </summary>
        /// <param name="where">Where条件</param>
        /// <returns></returns>
        protected LambdaUpdateHelper Where(WhereClip where)
        {
            IsChangeSql();
            this._WhereClip = where;
            return this;
        }


        /// <summary>
        /// 设置查询条件
        /// </summary>
        /// <param name="set">where条件</param>
        /// <returns></returns>
        protected LambdaUpdateHelper Set(WhereClip set)
        {
            IsChangeSql();
            this._SetClip = set;
            return this;
        }
        #endregion


        /// <summary>
        /// 执行的sql语句
        /// </summary>
        public string GetSqlString()
        {
            if (string.IsNullOrEmpty(_SqlString))
            {
                ReLoadParameters();
                _SqlString = DapperExtension.DapperImplementor.SqlGenerator.LambdaUpdate(this, ref _Parameters);
            }
            return _SqlString;

        }

        #region Execute
        /// <summary>
        /// 执行方法
        /// </summary>
        /// <returns></returns>
        public int Execute()
        {
            if (Transaction != null)
            {
                return DBUtils.GetDBHelper(DbType).ExecuteNonQuery(Transaction, this.GetSqlString(), DBUtils.ConvertToDbParameter(Parameters, DbType));
            }
            else
            {
                return DBUtils.GetDBHelper(DbType).ExecuteNonQuery(Connection, this.GetSqlString(), DBUtils.ConvertToDbParameter(Parameters, DbType));
            }
        }
        #endregion


        #region Private方法

        /// <summary>
        /// 是否修改sql
        /// </summary>
        private void IsChangeSql()
        {
            _SqlString = string.Empty;
        }


        /// <summary>
        /// 重新加载参数
        /// </summary>
        private void LoadParameters()
        {
            if (null == _Parameters || _Parameters.Count == 0)
            {
                if (!WhereClip.IsNullOrEmpty(_WhereClip))
                {
                    foreach (var item in _WhereClip.Parameters)
                    {
                        _Parameters.Add(item.ParameterName, item);
                    }
                }
                if (_Joins != null && _Joins.Count > 0)
                {
                    foreach (var item in _Joins)
                    {
                        foreach (var p in item.Value.Value.Parameters)
                        {
                            _Parameters.Add(p.ParameterName, p);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 重写加载参数
        /// </summary>
        private void ReLoadParameters()
        {
            _Parameters.Clear();
            LoadParameters();
        }
        #endregion
    }
}
