using C1.Win.Chart;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DrillDown
{
    class DrillDownManager
    {
        IEnumerable<Item> _orignal { get; set; }
        FlexChartBase _chart { get; set; }
        Queue<string> _drillDownPath = new Queue<string>();
        private string _currentPath = string.Empty;

        private AggregateType _aggregateType = AggregateType.Sum;


        public event EventHandler OnDrillDownChanged;
        public CollectionView CurrentItems { get; set; }
        public Stack<DrillDownHistory> History { get; set; }
        public AggregateType AggregateType
        {
            get
            {
                return _aggregateType;
            }
            set
            {
                if (_aggregateType != value)
                {
                    _aggregateType = value;
                    this.CurrentItems = new CollectionView(this.CurrentItems.Raw, _currentPath, this.AggregateType);
                }    
            }
        }

        public Queue<string> DrillDownPath
        {
            get
            {
                return _drillDownPath;
            }
            set
            {
                if (_drillDownPath != value)
                {
                    _drillDownPath = value;
                    Refresh();
                }
            }
        }

        public DrillDownManager(FlexChartBase chart, IEnumerable<Item> orignalSource, Queue<string> drillDownPath, AggregateType type = AggregateType.Sum, string baseName = null)
        {
            this._chart = chart;
            this._orignal = orignalSource;
            this._drillDownPath.Clear();
            this._drillDownPath = drillDownPath;
            this.AggregateType = type;
            this.baseName = string.IsNullOrEmpty(baseName) ? "-=Root=-" : baseName;
            Refresh();
        }

        private string baseName;
        private void Refresh()
        {
            _currentPath = this._drillDownPath.Dequeue();
            this.CurrentItems = new CollectionView(this._orignal, _currentPath, this.AggregateType);
            History = new Stack<DrillDownHistory>();
            History.Push(
                new DrillDownHistory()
                {
                    DrillDownPath = _drillDownPath.ToArray(),
                    Name = baseName,
                    Path = _currentPath,
                    View = this.CurrentItems,
                }
            );
            if (OnDrillDownChanged != null)
            {
                this.OnDrillDownChanged(this, new EventArgs());
            }
        }

        public void DrillDown(int index)
        {
            if (CurrentItems!= null && this._drillDownPath != null && this._drillDownPath.Count > 0)
            {
                _currentPath = this._drillDownPath.Dequeue();
                CurrentItems = CurrentItems.DrillDown(index, _currentPath, this.AggregateType);
                if (CurrentItems != null)
                {
                    History.Push(
                        new DrillDownHistory()
                        {
                            DrillDownPath = _drillDownPath.ToArray(),
                            Name = CurrentItems.Name,
                            Path = _currentPath,
                            View = CurrentItems,
                        }
                    );
                    if (OnDrillDownChanged != null)
                    {
                        this.OnDrillDownChanged(this, new EventArgs());
                    }
                }
            }
        }

        public void GoBackTo(DrillDownHistory history)
        {
            if (!History.Contains(history))
            {
                return;
            }
            while (History.Peek() != history)
            {
                History.Pop();
            }

            _currentPath = history.Path;
            this.CurrentItems = new CollectionView(history.View.Raw, _currentPath, this.AggregateType);
            _drillDownPath = new Queue<string>(history.DrillDownPath);

            if (OnDrillDownChanged != null)
            {
                this.OnDrillDownChanged(this, new EventArgs());
            }
        }
    }

    public class DrillDownHistory
    {
        public string[] DrillDownPath { get; set; }
        public string Name { get; set; }
        public string Path { get; set; }
        public CollectionView View { get; set; }
    }
}
