using System.Collections.Generic;
using System.Linq;
using Sockeye.DataList;
using Sockeye.Biz;
using Newtonsoft.Json;


namespace Sockeye.Models
{
    internal sealed class DataListTableProcessingOptions : DataListProcessingBase
    {
        internal List<string> Columns { get; set; }
        internal const int MaxPageSize = 1000;
        internal const int DefaultOffset = 0;
        internal const int DefaultLimit = 25;
        internal int? Offset { get; set; }
        internal int? Limit { get; set; }
        //All columns that are hidden but are affecting the query (sorting, filtering)
        //so in UI can show that there are hidden columns affecting the result set
        internal List<string> HiddenAffectiveColumns { get; set; }

        internal DataListTableProcessingOptions(
            DataListTableRequest request,
            IDataListProcessing dataList,
            DataListColumnView savedView,
            DataListSavedFilter savedFilter,
            long userId,
            AuthorizationRoles userRoles)
        {
            HiddenAffectiveColumns = new List<string>();
            //set some values from request
            Limit = request.Limit;
            Offset = request.Offset;
            base.ClientCriteria = request.ClientCriteria;
            base.DataListKey = request.DataListKey;
            base.ClientTimeStamp = request.ClientTimeStamp;

            //SET COLUMNS
            Columns = JsonConvert.DeserializeObject<List<string>>(savedView.Columns);

            //SET SORTBY
            base.SortBy = JsonConvert.DeserializeObject<Dictionary<string, string>>(savedView.Sort);

            //SET FILTER
            if (request.FilterId != 0 && savedFilter != null)
                base.Filter = JsonConvert.DeserializeObject<List<DataListFilterOption>>(savedFilter.Filter);

            //ADD STATIC SERVER FILTERS
            List<DataListFilterOption> StaticServerFilterOptions = new List<DataListFilterOption>();
            if (dataList is IDataListInternalCriteria)
                StaticServerFilterOptions = ((IDataListInternalCriteria)dataList).DataListInternalCriteria(userId, userRoles, request.ClientCriteria);

            //Add the internal filters into the listoptions existing filters
            //NOTE: There is currently no overlap between internal filtered columns and filters coming from the client
            foreach (DataListFilterOption dfo in StaticServerFilterOptions)
                base.Filter.Add(dfo);

            SetHiddenAffectiveColumns(dataList);

        }

        internal List<string> AllUniqueColumnKeysReferenced
        {
            get
            {
                return Columns.Union(base.Filter.Select(z => z.Column).ToList()).ToList();

            }
        }

        //All columns that are hidden but are affecting the query (sorting, filtering)
        //so in UI can show that there are hidden columns affecting the result set
        internal void SetHiddenAffectiveColumns(IDataListProcessing dataList)
        {
            foreach (string s in base.Filter.Select(z => z.Column).ToList())
            {
                if (!s.StartsWith("meta") && !Columns.Contains(s))
                {
                    if (!HiddenAffectiveColumns.Contains(s))
                    {
                        HiddenAffectiveColumns.Add(s);
                    }
                }
            }


            foreach (string s in base.SortBy.Select(z => z.Key).ToList())
            {
                if (!s.StartsWith("meta") && !Columns.Contains(s))
                {
                    if (!HiddenAffectiveColumns.Contains(s))
                    {
                        HiddenAffectiveColumns.Add(s);
                    }
                }
            }
        }
    }
}