using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

namespace CK.SCP.Models
{
    public static class EntitiesHelper
    {


        public static string GetPropertiesString<T>(T t,bool withName = true)
        {
            var peroperties = t.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            var sb = new StringBuilder();
            foreach (var property in peroperties)
            {
                if (withName)
                    sb.Append($"{property.Name}:");
                sb.Append($"{property.GetValue(t)},");
            }
            return sb.ToString();
        }



        public static List<T> GetData<T, TKey>(DbContext db, Expression<Func<T, T>> select,
            Expression<Func<T, bool>> where, Expression<Func<T, TKey>> order)
            where T : class
        {
            var list = db.Set<T>()
                .Where(@where)
                .OrderBy(order)
                .Select(@select).ToList();
            return list;
        }


        public static List<dynamic> GetData<T, TKey>(DbContext db, Expression<Func<T, dynamic>> select,
            Expression<Func<T, bool>> where, Expression<Func<T, TKey>> order, out int count)
            where T : class
        {
            count = db.Set<T>().Where(@where).Count();
            var list = db.Set<T>()
                .Where(@where)
                .OrderBy(order)
                .Select(@select).ToList();
            return list;

        }

        public static List<dynamic> GetPagedDataAsc<T, TKey>(DbContext db, Expression<Func<T, dynamic>> select,
            Expression<Func<T, bool>> where, Expression<Func<T, TKey>> order, int pageIndex, int pageSize, out int total)
            where T : class
        {
            total = db.Set<T>().Where(@where).Count();
            var list = db.Set<T>()
                .Where(@where)
                .OrderBy(order)
                .Select(@select)
                .Skip((pageIndex - 1) * pageSize)
                .Take(pageSize).ToList();
            return list;

        }

        public static List<T> GetPagedDataAsc<T, TKey>(DbContext db, Expression<Func<T, T>> select,
            Expression<Func<T, bool>> where, Expression<Func<T, TKey>> order, int pageIndex, int pageSize, out int total)
            where T : class
        {
            total = db.Set<T>().Where(@where.Compile()).AsQueryable().Count();
            var list = db.Set<T>()
                .Where(@where.Compile()).AsQueryable()
                .OrderBy(order)
                .Select(@select)
                .Skip((pageIndex - 1) * pageSize)
                .Take(pageSize).ToList();
            return list;

        }

        public static List<T> GetPagedDataAsc<T, TKey>(List<T> sourceList, Expression<Func<T, T>> select,
            Expression<Func<T, bool>> where, Expression<Func<T, TKey>> order, int pageIndex, int pageSize, out int total)
            where T : class
        {
            List<T> list = null;
            total = 0;
            try
            {
                total = sourceList.Where(where.Compile()).AsQueryable().Count();


            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            try
            {
                list = sourceList.Where(@where.Compile()).AsQueryable()
                                 .OrderBy(order)
                                 .Select(@select)
                                 .Skip((pageIndex - 1) * pageSize)
                                 .Take(pageSize).ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }

            return list;

        }


        public static List<dynamic> GetPagedDataDesc<T, TKey>(DbContext db, Expression<Func<T, dynamic>> select,
            Expression<Func<T, bool>> where, Expression<Func<T, TKey>> order, int pageIndex, int pageSize, out int total)
            where T : class
        {
            total = db.Set<T>().Where(@where).Count();
            var list = db.Set<T>()
                .Where(@where)
                .OrderByDescending(order)
                .Select(@select)
                .Skip((pageIndex - 1) * pageSize)
                .Take(pageSize).ToList();
            return list;
        }

        public static List<T> GetPagedDataDesc<T, TKey>(DbContext db, Expression<Func<T, T>> select,
         Expression<Func<T, bool>> where, Expression<Func<T, TKey>> order, int pageIndex, int pageSize, out int total)
         where T : class
        {
            total = db.Set<T>().Where(@where).Count();
            var list = db.Set<T>()
                .Where(@where)
                .OrderByDescending(order)
                .Select(@select)
                .Skip((pageIndex - 1) * pageSize)
                .Take(pageSize).ToList();
            return list;
        }

        public static List<T> GetPagedDataDesc<T, TKey>(List<T> sourceList, Expression<Func<T, T>> select,
            Expression<Func<T, bool>> where, Expression<Func<T, TKey>> order, int pageIndex, int pageSize, out int total)
            where T : class
        {
            total = sourceList.Where(@where.Compile()).AsQueryable().Count();
            var list = sourceList
                .Where(@where.Compile()).AsQueryable()
                .OrderByDescending(order)
                .Select(@select)
                .Skip((pageIndex - 1) * pageSize)
                .Take(pageSize).ToList();
            return list;

        }
    }
}