using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Decal.Interop.Controls;
using Decal.Interop.Core;
using Decal.Interop.Inject;

namespace Decal.DecalControls
{
    [ComVisible(true)]
    [Guid("3839008F-AF5B-43FC-9F6A-3376B99E3DAF")]
    [ClassInterface(ClassInterfaceType.None)]
    [ComSourceInterfaces("Decal.Interop.Controls.IListEvents\0\0")]
    [ProgId("DecalControls.List")]
    public class ListImpl : ControlBase, IList
    {
        public event IListEvents_DestroyEventHandler Destroy;
        public event IListEvents_ChangeEventHandler Change;

        private readonly List<IListColumn> _columns = new List<IListColumn>();
        private readonly List<object[]> _rows = new List<object[]>();
        private int _scrollPosition;
        private bool _autoScroll;
        private int _accessRow, _accessCol;

        // IListDisp
        public int AddRow()
        {
            int totalDataCols = 0;
            foreach (var col in _columns)
                totalDataCols += col.DataColumns;

            _rows.Add(new object[Math.Max(1, totalDataCols)]);
            if (_autoScroll)
                _scrollPosition = Math.Max(0, _rows.Count - 1);
            Invalidate();
            return _rows.Count - 1;
        }

        public void DeleteRow(int nIndex)
        {
            if (nIndex >= 0 && nIndex < _rows.Count)
            {
                _rows.RemoveAt(nIndex);
                Invalidate();
            }
        }

        public object Data
        {
            get
            {
                if (_accessRow >= 0 && _accessRow < _rows.Count)
                {
                    var row = _rows[_accessRow];
                    if (_accessCol >= 0 && _accessCol < row.Length)
                        return row[_accessCol];
                }
                return null;
            }
            set
            {
                if (_accessRow >= 0 && _accessRow < _rows.Count)
                {
                    var row = _rows[_accessRow];
                    if (_accessCol >= 0 && _accessCol < row.Length)
                    {
                        row[_accessCol] = value;
                        Invalidate();
                        Change?.Invoke(ID, _accessCol, _accessRow);
                    }
                }
            }
        }

        public int RowEstimate { set { } }
        public int Count => _rows.Count;

        public int ColumnWidth
        {
            get => 0;
            set { }
        }

        public int Color { get; set; }

        public bool AutoScroll { get => _autoScroll; set => _autoScroll = value; }
        public int ScrollPosition { get => _scrollPosition; set { _scrollPosition = value; Invalidate(); } }

        public void Clear()
        {
            _rows.Clear();
            _scrollPosition = 0;
            Invalidate();
        }

        public void InsertRow(int lIndex)
        {
            int totalDataCols = 0;
            foreach (var col in _columns)
                totalDataCols += col.DataColumns;

            if (lIndex < 0) lIndex = 0;
            if (lIndex > _rows.Count) lIndex = _rows.Count;

            _rows.Insert(lIndex, new object[Math.Max(1, totalDataCols)]);
            Invalidate();
        }

        public void JumpToPosition(int newVal)
        {
            _scrollPosition = newVal;
            Invalidate();
        }

        public int CountCols => _columns.Count;

        // IList
        public int AddColumn(IListColumn pNewColumn)
        {
            _columns.Add(pNewColumn);
            return _columns.Count - 1;
        }

        public tagRECT CellRect => default;

        protected override void OnDestroy() => Destroy?.Invoke(ID);
    }
}
