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

namespace InABox.Core
{
    public abstract class LookupGenerator<T> : ILookupGenerator
    {
        private readonly List<Tuple<string, Type>> columns = new List<Tuple<string, Type>>();

        private readonly List<LookupEntry> entries = new List<LookupEntry>();

        public LookupGenerator(T[]? items)
        {
            Items = items;
        }

        /// <summary>
        /// Null is synonymous with an empty list.
        /// </summary>
        public T[]? Items { get; set; }

        public event GenerateLookupsHandler? OnBeforeGenerateLookups;
        public event GenerateLookupsHandler? OnAfterGenerateLookups;

        public CoreTable AsTable(string colname)
        {
            var result = new CoreTable();
            result.Columns.Add(new CoreColumn { ColumnName = colname, DataType = typeof(object) });
            result.Columns.Add(new CoreColumn { ColumnName = "Display", DataType = typeof(string) });
            foreach (var column in columns)
                result.Columns.Add(new CoreColumn { ColumnName = column.Item1, DataType = column.Item2 });

            GenerateLookups();

            foreach (var entry in entries)
            {
                var row = result.NewRow();
                row[colname] = entry.Key;
                row["Display"] = entry.Display;
                for (var i = 0; i < columns.Count; i++)
                    row[columns[i].Item1] = entry.Values[i];
                result.Rows.Add(row);
            }

            return result;
        }

        private void GenerateLookups()
        {
            OnBeforeGenerateLookups?.Invoke(this, entries);
            DoGenerateLookups();
            OnAfterGenerateLookups?.Invoke(this, entries);
        }

        protected virtual void DoGenerateLookups()
        {
        }

        protected void Clear()
        {
            entries.Clear();
        }

        protected LookupEntry AddValue(object key, string display, params object[] values)
        {
            if (values.Length != columns.Count)
                throw new Exception("Incorrect # of values in " + GetType().Name);
            var result = new LookupEntry(key, display, values);
            entries.Add(result);
            return result;
        }

        protected void AddColumn(string name, Type type)
        {
            if (!columns.Any(x=>String.Equals(x.Item1,name)))
                columns.Add(new Tuple<string, Type>(name, type));
        }
    }
}