using System.Collections.Generic;
using System.Linq;
using System.Text;
using AyaNova.Biz;
using Newtonsoft.Json.Linq;
using Microsoft.EntityFrameworkCore;

namespace AyaNova.DataList
{

    /// <summary>
    /// DataList object base class
    /// </summary>
    internal abstract class AyaDataList : IAyaDataList
    {

        public AyaDataList()
        {

        }

        public string SQLFrom { get; set; }
        public List<AyaDataListFieldDefinition> FieldDefinitions { get; set; }
        public AuthorizationRoles AllowedRoles { get; set; }
        public AyaType DefaultListObjectType { get; set; }

        public string DefaultListView { get; set; }


        //return array of field keys in list view
        public List<string> GetFieldListFromListView(JArray listViewArray)
        {
            //  [{key:"COLUMN UNIQUE KEY ID",sort:"-" or "+",filter:{any:true/false,items:[{FILTER OBJECT SEE BELOW}]} }, {key:"second column unique key"},{...etc...}]
            List<string> ret = new List<string>();
            for (int i = 0; i < listViewArray.Count; i++)
            {
                var cm = listViewArray[i];
                ret.Add(cm["fld"].Value<string>());
            }
            return ret;
        }



        public Newtonsoft.Json.Linq.JArray GenerateListColumnsJSONFromListView(JArray listViewArray)
        {

            var ListViewFieldKeys = GetFieldListFromListView(listViewArray);
            var CustomFieldDefinitions = GetCustomFieldDefinitionsForList();

            //Generate JSON fragment to return with column definitions
            StringBuilder sb = new StringBuilder();

            sb.Append("[");

            bool FirstColumnAdded = false;

            foreach (string s in ListViewFieldKeys)
            {
                AyaDataListFieldDefinition o = FieldDefinitions.FirstOrDefault(z => z.FieldKey == s);
#if (DEBUG)
                //Developers little helper
                if (o == null)
                {
                    throw new System.ArgumentNullException($"DEV ERROR in AyaDataList::GenerateListColumnsJSONFromListView - field {s} specified in ListView was NOT found in ObjectFields list");
                }
#endif

                if (o != null)
                {//Here is where we can vet the field name, if it doesn't exist. For production we'll just ignore those ones

                    if (FirstColumnAdded)
                        sb.Append(",");
                    sb.Append("{");
                    //Build required part of column definition
                    if (!o.IsCustomField)
                        sb.Append($"\"cm\":\"{o.TKey}\",\"dt\":{(int)o.UiFieldDataType}");
                    else
                    {
                        //insert specific type for this custom field
                        if (CustomFieldDefinitions.ContainsKey(o.TKey))
                        {
                            var customFieldType = CustomFieldDefinitions[o.TKey];
                            sb.Append($"\"cm\":\"{o.TKey}\",\"dt\":{customFieldType}");
                        }
                        else
                        {
                            //this is normal as there may not be a definition for a Custom field but it's been requested so just treat it like text                            
                            sb.Append($"\"cm\":\"{o.TKey}\",\"dt\":{(int)UiFieldDataType.Text}");
                        }
                    }

                    //Has a AyObjectType? (linkable / openable)
                    if (o.AyaObjectType != 0)
                        sb.Append($",\"ay\":{(int)o.AyaObjectType}");

                    //Row ID column?
                    if (o.IsRowId)
                    {
                        sb.Append($",\"rid\":1");
                    }

                    //Has a Enumtype?
                    if (!string.IsNullOrEmpty(o.EnumType))
                        sb.Append($",\"et\":\"{AyaNova.Util.StringUtil.TrimTypeName(o.EnumType)}\"");

                    sb.Append("}");
                    FirstColumnAdded = true;

                }
            }
            sb.Append("]");

            return JArray.Parse(sb.ToString());
        }


        //Find and return a dictionary of all custom fields definitions for all types in list
        //used to build the column array and define specific type defined for custom fields so client datatable 
        //knows how to format it
        private Dictionary<string, int> GetCustomFieldDefinitionsForList()
        {
            //all keys and types can go in the same list since they are unique to each type of list
            //i.e. both users and widget custom fields can be in the same list
            Dictionary<string, int> ret = new Dictionary<string, int>();
            List<string> typesProcessed = new List<string>();
            //custom fields handling
            foreach (AyaDataListFieldDefinition d in this.FieldDefinitions)
            {
                if (d.IsCustomField)
                {
                    //this relies on the convention I'm using of AyaType name as the first part of all custom fields lT keys, e.g.
                    //WidgetCustom1 -> Widget
                    var ayatypename = d.TKey.Split("Custom")[0];
                    if (!typesProcessed.Contains(ayatypename))
                    {
                        //make sure we do each type only once
                        typesProcessed.Add(ayatypename);
                        //fetch it and set it
                        using (var ct = AyaNova.Util.ServiceProviderProvider.DBContext)
                        {
                            var fc = ct.FormCustom.AsNoTracking().SingleOrDefault(z => z.FormKey == ayatypename);
                            //This  is normal and expected in an empty db, removing this block
                            // #if (DEBUG)
                            //                             if (fc == null)
                            //                             {
                            //                                 throw new System.ArgumentNullException($"AyaDataList:GetCustomFieldDefinitionsForList, Custom field object type {ayatypename} has no FormCustom defined");
                            //                             }
                            // #endif
                            //production handling of missing formcustom
                            if (fc == null)
                                continue;

                            //iterate the fields and add each custom one with a type to the return dictionary
                            var flds = JArray.Parse(fc.Template);
                            foreach (JToken t in flds)
                            {
                                if (t["type"] != null)
                                {
                                    ret.Add(t["fld"].Value<string>(), t["type"].Value<int>());
                                }
                            }


                        }

                    }
                }
            }
            /*{[
              {
                "fld": "Notes",
                "required": true
              },
              {
                "fld": "WidgetCustom1",
                "required": false,
                "type": 1
              },
              {
                "fld": "WidgetCustom2",
                "required": true,
                "type": 4
              },
              {
                "fld": "WidgetCustom3",
                "required": false,
                "type": 5
              },
              {
                "fld": "WidgetCustom4",
                "required": false,
                "type": 6
              },
              {
                "fld": "WidgetCustom5",
                "required": false,
                "type": 8
              },
              {
                "fld": "WidgetCustom6",
                "required": false,
                "type": 2
              },
              {
                "fld": "WidgetCustom7",
                "required": false,
                "type": 3
              }
            ]}*/
            return ret;

        }



    }//eoc

}//eons