using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace NGnono.Framework.Models
{
    /// <summary>
    ///     ¿É·ÖÒ³µÄ
    /// </summary>
    public interface IPagerable
    {
        /// <summary>
        ///     Ò³Âë(´Ó1ÆðÊ¼)
        /// </summary>
        int Index { get; }

        /// <summary>
        ///     Ò³´óÐ¡
        /// </summary>
        int Size { get; }

        /// <summary>
        ///     ×ÜÒ³Êý
        /// </summary>
        int TotalPaged { get; }

        /// <summary>
        ///     ×Ü¼ÇÂ¼Êý
        /// </summary>
        int TotalCount { get; }
    }

    /// <summary>
    ///     ¿É·ÖÒ³µü´úÆ÷
    /// </summary>
    /// <typeparam name="T">ÀàÐÍ</typeparam>
    public interface IPagerEnumerable<out T> : IEnumerable<T>, IPagerable
    {
    }

    /// <summary>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class PagerInfo<T> : List<T>, IPagerEnumerable<T>
    {
        #region fields

        #endregion

        #region .ctor

        /// <summary>
        /// </summary>
        public PagerInfo()
        {
        }

        /// <summary>
        /// </summary>
        /// <param name="request"></param>
        public PagerInfo(PagerRequest request)
            : this(request, 0)
        {
        }

        /// <summary>
        /// </summary>
        /// <param name="request"></param>
        /// <param name="totalCount"></param>
        public PagerInfo(PagerRequest request, int totalCount)
        {
            Index = request.PageIndex;
            Size = request.PageSize;
            TotalCount = totalCount;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <param name="totalCount"></param>
        /// <param name="data"></param>
        public PagerInfo(PagerRequest request, int totalCount, IEnumerable<T> data)
            : this(request, totalCount)
        {
            AddRange(data);
        }

        #endregion

        #region properties

        /// <summary>
        ///     ÊÇ·ñ´æÔÚ·ÖÒ³
        /// </summary>
        [DataMember(Name = "ispaged", Order = 5)]
        public bool IsPaged
        {
            get { return Size < TotalCount; }
        }

        /// <summary>
        ///     Ë÷Òý
        /// </summary>
        [DataMember(Name = "pageindex", Order = 1)]
        public int Index { get; set; }

        /// <summary>
        ///     ´óÐ¡
        /// </summary>
        [DataMember(Name = "pagesize", Order = 2)]
        public int Size { get; set; }

        /// <summary>
        ///     ×ÜÊý¾ÝÁ¿
        /// </summary>
        [DataMember(Name = "totalcount", Order = 3)]
        public int TotalCount { get; set; }

        /// <summary>
        ///     ×ÜÒ³Êý
        /// </summary>
        [DataMember(Name = "totalpaged", Order = 4)]
        public int TotalPaged
        {
            get { return (int)Math.Ceiling(TotalCount / (double)Size); }
        }

        #endregion

        #region methods

        #endregion
    }

    /// <summary>
    ///     ·ÖÒ³ÇëÇó
    /// </summary>
    [DataContract]
    public class PagerRequest
    {
        private readonly int _maxPageSize;

        /// <summary>
        ///     local pageNumber
        /// </summary>
        private int _pageIndex;

        /// <summary>
        ///     local pageSize
        /// </summary>
        private int _pageSize;

        /// <summary>
        /// </summary>
        public PagerRequest()
            : this(40)
        {
        }

        /// <summary>
        /// </summary>
        /// <param name="maxPageSize"></param>
        public PagerRequest(int maxPageSize)
        {
            _maxPageSize = maxPageSize;
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="PagerRequest" /> class.
        /// </summary>
        /// <param name="pageNumber">
        ///     The page number.
        /// </param>
        /// <param name="pageSize">
        ///     The page size.
        /// </param>
        public PagerRequest(int pageNumber, int pageSize)
            : this(pageNumber, pageSize, 40)
        {
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="PagerRequest" /> class.
        /// </summary>
        /// <param name="pageNumber">
        ///     The page number.
        /// </param>
        /// <param name="pageSize">
        ///     The page size.
        /// </param>
        /// <param name="maxPageSize"> </param>
        public PagerRequest(int pageNumber, int pageSize, int maxPageSize)
            : this(maxPageSize)
        {
            PageSize = pageSize;
            PageIndex = pageNumber;
        }

        /// <summary>
        ///     Ò³´óÐ¡
        /// </summary>
        [DataMember]
        public int PageSize
        {
            get { return _pageSize; }

            private set { _pageSize = (value < 1 ? 1 : (value > _maxPageSize ? _maxPageSize : value)); }
        }

        /// <summary>
        ///     Ò³Âë
        /// </summary>
        [DataMember]
        public int PageIndex
        {
            get { return _pageIndex; }

            private set { _pageIndex = value < 1 ? 1 : value; }
        }
    }
}