using MediaBrowser.Model.Activity;
using MediaBrowser.Model.Querying;
using System.Collections.Generic;
using System.Linq;
using MediaBrowser.Controller.Library;
namespace MediaBrowser.Api.Reports
{
    ///  A report activities builder. 
    /// 
    public class ReportActivitiesBuilder : ReportBuilderBase
    {
        #region [Constructors]
        /// 
        /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportActivitiesBuilder class. 
        ///  Manager for library. 
        ///  Manager for user. 
        public ReportActivitiesBuilder(ILibraryManager libraryManager, IUserManager userManager)
            : base(libraryManager)
        {
            _userManager = userManager;
        }
        #endregion
        #region [Private Fields]
        private readonly IUserManager _userManager; ///< Manager for user
        #endregion
        #region [Public Methods]
        ///  Gets a result. 
        ///  The query result. 
        ///  The request. 
        ///  The result. 
        public ReportResult GetResult(QueryResult queryResult, IReportsQuery request)
        {
            ReportDisplayType displayType = ReportHelper.GetReportDisplayType(request.DisplayType);
            List> options = this.GetReportOptions(request,
                () => this.GetDefaultHeaderMetadata(),
                (hm) => this.GetOption(hm)).Where(x => this.DisplayTypeVisible(x.Header.DisplayType, displayType)).ToList();
            var headers = GetHeaders(options);
            var rows = GetReportRows(queryResult.Items, options);
            ReportResult result = new ReportResult { Headers = headers };
            HeaderMetadata groupBy = ReportHelper.GetHeaderMetadataType(request.GroupBy);
            int i = headers.FindIndex(x => x.FieldName == groupBy);
            if (groupBy != HeaderMetadata.None && i >= 0)
            {
                var rowsGroup = rows.SelectMany(x => x.Columns[i].Name.Split(';'), (x, g) => new { Group = g.Trim(), Rows = x })
                    .GroupBy(x => x.Group)
                    .OrderBy(x => x.Key)
                    .Select(x => new ReportGroup { Name = x.Key, Rows = x.Select(r => r.Rows).ToList() });
                result.Groups = rowsGroup.ToList();
                result.IsGrouped = true;
            }
            else
            {
                result.Rows = rows;
                result.IsGrouped = false;
            }
            return result;
        }
        #endregion
        #region [Protected Internal Methods]
        ///  Gets the headers. 
        ///  Type of the header. 
        ///  The request. 
        ///  The headers. 
        /// 
        protected internal override List GetHeaders(H request)
        {
            return this.GetHeaders(request, () => this.GetDefaultHeaderMetadata(), (hm) => this.GetOption(hm));
        }
        #endregion
        #region [Private Methods]
        ///  Gets default header metadata. 
        ///  The default header metadata. 
        private List GetDefaultHeaderMetadata()
        {
            return new List
					{
                        HeaderMetadata.UserPrimaryImage,
                        HeaderMetadata.Date,
                        HeaderMetadata.User,
                        HeaderMetadata.Type,
                        HeaderMetadata.Severity,
						HeaderMetadata.Name,
                        HeaderMetadata.ShortOverview,
						HeaderMetadata.Overview,
                        //HeaderMetadata.UserId
                        //HeaderMetadata.Item,
					};
        }
        ///  Gets an option. 
        ///  The header. 
        ///  The sort field. 
        ///  The option. 
        private ReportOptions GetOption(HeaderMetadata header, string sortField = "")
        {
            HeaderMetadata internalHeader = header;
            ReportOptions option = new ReportOptions()
            {
                Header = new ReportHeader
                {
                    HeaderFieldType = ReportFieldType.String,
                    SortField = sortField,
                    Type = "",
                    ItemViewType = ItemViewType.None
                }
            };
            switch (header)
            {
                case HeaderMetadata.Name:
                    option.Column = (i, r) => i.Name;
                    option.Header.SortField = "";
                    break;
                case HeaderMetadata.Overview:
                    option.Column = (i, r) => i.Overview;
                    option.Header.SortField = "";
                    option.Header.CanGroup = false;
                    break;
                case HeaderMetadata.ShortOverview:
                    option.Column = (i, r) => i.ShortOverview;
                    option.Header.SortField = "";
                    option.Header.CanGroup = false;
                    break;
                case HeaderMetadata.Type:
                    option.Column = (i, r) => i.Type;
                    option.Header.SortField = "";
                    break;
                case HeaderMetadata.Date:
                    option.Column = (i, r) => i.Date;
                    option.Header.SortField = "";
                    option.Header.HeaderFieldType = ReportFieldType.DateTime;
                    option.Header.Type = "";
                    break;
                case HeaderMetadata.UserPrimaryImage:
                    //option.Column = (i, r) => i.UserPrimaryImageTag;
                    option.Header.DisplayType = ReportDisplayType.Screen;
                    option.Header.ItemViewType = ItemViewType.UserPrimaryImage;
                    option.Header.ShowHeaderLabel = false;
                    internalHeader = HeaderMetadata.User;
                    option.Header.CanGroup = false;
                    option.Column = (i, r) =>
                    {
                        if (!string.IsNullOrEmpty(i.UserId))
                        {
                            MediaBrowser.Controller.Entities.User user = _userManager.GetUserById(i.UserId);
                            if (user != null)
                            {
                                var dto = _userManager.GetUserDto(user);
                                return dto.PrimaryImageTag;
                            }
                        }
                        return string.Empty;
                    };
                    option.Header.SortField = "";
                    break;
                case HeaderMetadata.Severity:
                    option.Column = (i, r) => i.Severity;
                    option.Header.SortField = "";
                    break;
                case HeaderMetadata.Item:
                    option.Column = (i, r) => i.ItemId;
                    option.Header.SortField = "";
                    break;
                case HeaderMetadata.User:
                    option.Column = (i, r) =>
                    {
                        if (!string.IsNullOrEmpty(i.UserId))
                        {
                            MediaBrowser.Controller.Entities.User user = _userManager.GetUserById(i.UserId);
                            if (user != null)
                                return user.Name;
                        }
                        return string.Empty;
                    };
                    option.Header.SortField = "";
                    break;
                case HeaderMetadata.UserId:
                    option.Column = (i, r) => i.UserId;
                    option.Header.SortField = "";
                    break;
            }
            option.Header.Name = GetLocalizedHeader(internalHeader);
            option.Header.FieldName = header;
            return option;
        }
        ///  Gets report rows. 
        ///  The items. 
        ///  Options for controlling the operation. 
        ///  The report rows. 
        private List GetReportRows(IEnumerable items, List> options)
        {
            var rows = new List();
            foreach (ActivityLogEntry item in items)
            {
                ReportRow rRow = GetRow(item);
                foreach (ReportOptions option in options)
                {
                    object itemColumn = option.Column != null ? option.Column(item, rRow) : "";
                    object itemId = option.ItemID != null ? option.ItemID(item) : "";
                    ReportItem rItem = new ReportItem
                    {
                        Name = ReportHelper.ConvertToString(itemColumn, option.Header.HeaderFieldType),
                        Id = ReportHelper.ConvertToString(itemId, ReportFieldType.Object)
                    };
                    rRow.Columns.Add(rItem);
                }
                rows.Add(rRow);
            }
            return rows;
        }
        ///  Gets a row. 
        ///  The item. 
        ///  The row. 
        private ReportRow GetRow(ActivityLogEntry item)
        {
            ReportRow rRow = new ReportRow
            {
                Id = item.Id,
                UserId = item.UserId
            };
            return rRow;
        }
        #endregion
    }
}