using System;
using System.Collections.Generic;
using System.Linq;

namespace InABox.Core
{
    public enum ImportMappingType
    {
        Import,
        Export
    }

    public static class ImportFactory
    {
        private static readonly List<ImportDefinition> _definitions = new List<ImportDefinition>();

        public static ImportDefinition[] Definitions => _definitions.ToArray();

        public static IEnumerable<ImportMapping> ExtractMappings(Type type, ImportMappingType Import)
        {
            var results = new List<ImportMapping>();
            
            var props = DatabaseSchema.Properties(type).OrderBy(x=>x.Sequence);
            
            //var keys = CoreUtils.PropertyList(type, x => true, true).Keys.ToArray();
            foreach (var prop in props)
            {

                if (prop.Editor != null && prop.Editor is NullEditor == false && (!prop.IsCalculated || Import == ImportMappingType.Export))
                {
                    var bOK = true;

                    var bKey = prop.Editor is UniqueCodeEditor;

                    var lookup = ImportLookupType.None;
                    if (Import == ImportMappingType.Import)
                    {
                        var comps = prop.Name.Split('.');
                        if (comps.Length > 1)
                        {
                            if ((comps.Length == 2) && (prop.Editor is CodeEditor))
                                lookup = ImportLookupType.Restrict;
                            else
                                bOK = false;
                        }
                    }

                    if (bOK)
                        results.Add(new ImportMapping { Property = prop.Name, Field = "", Constant = "", Lookup = lookup, Key = bKey });
                }
            }

            return results;
        }

        private static bool IsNestedEntityLink(Type type, string property)
        {
            if (String.IsNullOrWhiteSpace(property))
                return false;
            var parent = string.Join(".", property.Split('.').Reverse().Skip(1).Reverse());
            if (!string.IsNullOrEmpty(parent))
            {
                var parentprop = CoreUtils.GetProperty(type, parent);
                if (parentprop.PropertyType.GetInterfaces().Contains(typeof(IEntityLink)))
                    return true;
                return IsNestedEntityLink(type,parent);
            }
            return false;
        }

        public static void Register(Type type, string description, string filter)
        {
            if (!_definitions.Any(x => x.Type.Equals(type)))
                _definitions.Add(new ImportDefinition(type, description, filter));
        }

        public static IImporter Create(ImportDefinition definition, Type type)
        {
            var importer = definition.Type.MakeGenericType(type);
            var result = Activator.CreateInstance(importer) as IImporter;
            return result;
        }

        //public static IImporter<T> Create<T>(ImportDefinition definition) where T : new()
        //{
        //    var importer = definition.Type.MakeGenericType(typeof(T));
        //    var result = Activator.CreateInstance(importer) as IImporter<T>;
        //    return result;
        //}
    }
}