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

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 FullListAllowedRoles { get; set; }
        public AuthorizationRoles MiniListAllowedRoles { get; set; }
        public AyaType DefaultListObjectType { get; set; }
        public string ListKey { get; set; }
        public string DefaultDataListDisplayTemplate { get; set; }

        public Newtonsoft.Json.Linq.JArray GenerateMINIListColumnsJSON()
        {
            //return $"[ {{\"cm\":\"df\",\"dt\":0,\"ay\":{(int)DefaultListObjectType}}},{{\"cm\":\"Widget\",\"dt\":{(int)AyaUiFieldDataType.Text},\"ay\":{(int)DefaultListObjectType}}}]";
            return JArray.Parse($"[ {{\"cm\":\"df\",\"dt\":0,\"ay\":{(int)DefaultListObjectType}}},{{\"cm\":\"Widget\",\"dt\":{(int)UiFieldDataType.Text},\"ay\":{(int)DefaultListObjectType}}}]");
        }

        public Newtonsoft.Json.Linq.JArray GenerateListColumnsJSONFromTemplate(string template)
        {
            //parse the template
            var jtemplate = JObject.Parse(template);


            //convert to strings (https://stackoverflow.com/a/33836599/8939)
            var fullFields = ((JArray)jtemplate["full"]).ToObject<string[]>();

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

            sb.Append("[");
            //df First column is always the df column
            sb.Append($"{{\"cm\":\"df\",\"dt\":0,\"ay\":{(int)DefaultListObjectType}}}");

            foreach (string s in fullFields)
            {
                AyaDataListFieldDefinition o = FieldDefinitions.FirstOrDefault(x => x.FieldKey == s);
#if (DEBUG)
                //Developers little helper
                if (o == null)
                {
                    throw new System.ArgumentNullException($"DEV ERROR in AyaDataList::GenerateListColumnsJSONFromTemplate - field {s} specified in template 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

                    sb.Append(",");
                    sb.Append("{");
                    //Build required part of column definition
                    sb.Append($"\"cm\":\"{o.LtKey}\",\"dt\":{(int)o.UiFieldDataType}");

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

                    sb.Append("}");

                }
            }
            sb.Append("]");

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

        //make sure the template parses and all the fields specified are really existant
        //this is more for dev errors or api users becuase the client shouldn't generate bad templates
        public bool ValidateTemplate(string template)
        {
            try
            {
                //parse the template
                var jtemplate = JObject.Parse(template);
                var fullFields = ((JArray)jtemplate["full"]).ToObject<string[]>();
                var miniFields = ((JArray)jtemplate["mini"]).ToObject<string[]>();

                foreach (string s in fullFields)
                {
                    AyaDataListFieldDefinition o = FieldDefinitions.FirstOrDefault(x => x.FieldKey == s);
                    if (o == null)
                    {
                        return false;
                    }
                }

                foreach (string s in miniFields)
                {
                    AyaDataListFieldDefinition o = FieldDefinitions.FirstOrDefault(x => x.FieldKey == s);
                    if (o == null)
                    {
                        return false;
                    }
                }
            }
            catch
            {
                return false;
            }

            return true;
        }

    }//eoc

}//eons