using System.Collections.Generic;
using FairyGUI.Utils;
using System;
namespace FairyGUI
{
    /// 
    /// Controller class.
    /// 控制器类。控制器的创建和设计需通过编辑器完成,不建议使用代码创建。
    /// 最常用的方法是通过selectedIndex获得或改变控制器的活动页面。如果要获得控制器页面改变的通知,使用onChanged事件。
    /// 
    public class Controller : EventDispatcher
    {
        /// 
        /// Name of the controller
        /// 控制器名称。
        /// 
        public string name;
        internal GComponent parent;
        internal bool autoRadioGroupDepth;
        internal bool changing;
        int _selectedIndex;
        int _previousIndex;
        List _pageIds;
        List _pageNames;
        List _actions;
        EventListener _onChanged;
        static uint _nextPageId;
        public Controller()
        {
            _pageIds = new List();
            _pageNames = new List();
            _selectedIndex = -1;
            _previousIndex = -1;
        }
        public void Dispose()
        {
            RemoveEventListeners();
        }
        /// 
        /// When controller page changed.
        /// 当控制器活动页面改变时,此事件被触发。
        /// 
        public EventListener onChanged
        {
            get { return _onChanged ?? (_onChanged = new EventListener(this, "onChanged")); }
        }
        /// 
        /// Current page index.
        /// 获得或设置当前活动页面索引。
        /// 
        public int selectedIndex
        {
            get
            {
                return _selectedIndex;
            }
            set
            {
                if (_selectedIndex != value)
                {
                    if (value > _pageIds.Count - 1)
                        throw new IndexOutOfRangeException("" + value);
                    changing = true;
                    _previousIndex = _selectedIndex;
                    _selectedIndex = value;
                    parent.ApplyController(this);
                    DispatchEvent("onChanged", null);
                    changing = false;
                }
            }
        }
        /// 
        /// Set current page index, no onChanged event.
        /// 通过索引设置当前活动页面,和selectedIndex的区别在于,这个方法不会触发onChanged事件。
        /// 
        /// Page index
        public void SetSelectedIndex(int value)
        {
            if (_selectedIndex != value)
            {
                if (value > _pageIds.Count - 1)
                    throw new IndexOutOfRangeException("" + value);
                changing = true;
                _previousIndex = _selectedIndex;
                _selectedIndex = value;
                parent.ApplyController(this);
                changing = false;
            }
        }
        /// 
        /// Set current page by name, no onChanged event.
        /// 通过页面名称设置当前活动页面,和selectedPage的区别在于,这个方法不会触发onChanged事件。
        /// 
        /// Page name
        public void SetSelectedPage(string value)
        {
            int i = _pageNames.IndexOf(value);
            if (i == -1)
                i = 0;
            this.SetSelectedIndex(i);
        }
        /// 
        /// Current page name.
        /// 获得当前活动页面名称
        /// 
        public string selectedPage
        {
            get
            {
                if (_selectedIndex == -1)
                    return null;
                else
                    return _pageNames[_selectedIndex];
            }
            set
            {
                int i = _pageNames.IndexOf(value);
                if (i == -1)
                    i = 0;
                this.selectedIndex = i;
            }
        }
        /// 
        /// Previouse page index.
        /// 获得上次活动页面索引
        /// 
        public int previsousIndex
        {
            get { return _previousIndex; }
        }
        /// 
        /// Previous page name.
        /// 获得上次活动页面名称。
        /// 
        public string previousPage
        {
            get
            {
                if (_previousIndex == -1)
                    return null;
                else
                    return _pageNames[_previousIndex];
            }
        }
        /// 
        /// Page count of this controller.
        /// 获得页面数量。
        /// 
        public int pageCount
        {
            get { return _pageIds.Count; }
        }
        /// 
        /// Get page name by an index.
        /// 通过页面索引获得页面名称。
        /// 
        /// Page index
        /// Page Name
        public string GetPageName(int index)
        {
            return _pageNames[index];
        }
        /// 
        /// Get page id by an index.
        /// 通过页面索引获得页面id。
        /// 
        /// Page index
        /// Page Id
        public string GetPageId(int index)
        {
            return _pageIds[index];
        }
        /// 
        /// Get page id by name
        /// 
        /// 
        /// 
        public string GetPageIdByName(string aName)
        {
            int i = _pageNames.IndexOf(aName);
            if (i != -1)
                return _pageIds[i];
            else
                return null;
        }
        /// 
        /// Add a new page to this controller.
        /// 
        /// Page name
        public void AddPage(string name)
        {
            if (name == null)
                name = string.Empty;
            AddPageAt(name, _pageIds.Count);
        }
        /// 
        /// Add a new page to this controller at a certain index.
        /// 
        /// Page name
        /// Insert position
        public void AddPageAt(string name, int index)
        {
            string nid = "_" + (_nextPageId++);
            if (index == _pageIds.Count)
            {
                _pageIds.Add(nid);
                _pageNames.Add(name);
            }
            else
            {
                _pageIds.Insert(index, nid);
                _pageNames.Insert(index, name);
            }
        }
        /// 
        /// Remove a page.
        /// 
        /// Page name
        public void RemovePage(string name)
        {
            int i = _pageNames.IndexOf(name);
            if (i != -1)
            {
                _pageIds.RemoveAt(i);
                _pageNames.RemoveAt(i);
                if (_selectedIndex >= _pageIds.Count)
                    this.selectedIndex = _selectedIndex - 1;
                else
                    parent.ApplyController(this);
            }
        }
        /// 
        /// Removes a page at a certain index.
        /// 
        /// 
        public void RemovePageAt(int index)
        {
            _pageIds.RemoveAt(index);
            _pageNames.RemoveAt(index);
            if (_selectedIndex >= _pageIds.Count)
                this.selectedIndex = _selectedIndex - 1;
            else
                parent.ApplyController(this);
        }
        /// 
        /// Remove all pages.
        /// 
        public void ClearPages()
        {
            _pageIds.Clear();
            _pageNames.Clear();
            if (_selectedIndex != -1)
                this.selectedIndex = -1;
            else
                parent.ApplyController(this);
        }
        /// 
        /// Check if the controller has a page.
        /// 
        /// Page name.
        /// 
        public bool HasPage(string aName)
        {
            return _pageNames.IndexOf(aName) != -1;
        }
        internal int GetPageIndexById(string aId)
        {
            return _pageIds.IndexOf(aId);
        }
        internal string GetPageNameById(string aId)
        {
            int i = _pageIds.IndexOf(aId);
            if (i != -1)
                return _pageNames[i];
            else
                return null;
        }
        internal string selectedPageId
        {
            get
            {
                if (_selectedIndex == -1)
                    return string.Empty;
                else
                    return _pageIds[_selectedIndex];
            }
            set
            {
                int i = _pageIds.IndexOf(value);
                if (i != -1)
                    this.selectedIndex = i;
            }
        }
        internal string oppositePageId
        {
            set
            {
                int i = _pageIds.IndexOf(value);
                if (i > 0)
                    this.selectedIndex = 0;
                else if (_pageIds.Count > 1)
                    this.selectedIndex = 1;
            }
        }
        internal string previousPageId
        {
            get
            {
                if (_previousIndex == -1)
                    return null;
                else
                    return _pageIds[_previousIndex];
            }
        }
        public void RunActions()
        {
            if (_actions != null)
            {
                int cnt = _actions.Count;
                for (int i = 0; i < cnt; i++)
                {
                    _actions[i].Run(this, previousPageId, selectedPageId);
                }
            }
        }
        public void Setup(ByteBuffer buffer)
        {
            int beginPos = buffer.position;
            buffer.Seek(beginPos, 0);
            name = buffer.ReadS();
            autoRadioGroupDepth = buffer.ReadBool();
            buffer.Seek(beginPos, 1);
            int cnt = buffer.ReadShort();
            _pageIds.Capacity = cnt;
            _pageNames.Capacity = cnt;
            for (int i = 0; i < cnt; i++)
            {
                _pageIds.Add(buffer.ReadS());
                _pageNames.Add(buffer.ReadS());
            }
            int homePageIndex = 0;
            if (buffer.version >= 2)
            {
                int homePageType = buffer.ReadByte();
                switch (homePageType)
                {
                    case 1:
                        homePageIndex = buffer.ReadShort();
                        break;
                    case 2:
                        homePageIndex = _pageNames.IndexOf(UIPackage.branch);
                        if (homePageIndex == -1)
                            homePageIndex = 0;
                        break;
                    case 3:
                        homePageIndex = _pageNames.IndexOf(UIPackage.GetVar(buffer.ReadS()));
                        if (homePageIndex == -1)
                            homePageIndex = 0;
                        break;
                }
            }
            buffer.Seek(beginPos, 2);
            cnt = buffer.ReadShort();
            if (cnt > 0)
            {
                if (_actions == null)
                    _actions = new List(cnt);
                for (int i = 0; i < cnt; i++)
                {
                    int nextPos = buffer.ReadUshort();
                    nextPos += buffer.position;
                    ControllerAction action = ControllerAction.CreateAction((ControllerAction.ActionType)buffer.ReadByte());
                    action.Setup(buffer);
                    _actions.Add(action);
                    buffer.position = nextPos;
                }
            }
            if (parent != null && _pageIds.Count > 0)
                _selectedIndex = homePageIndex;
            else
                _selectedIndex = -1;
        }
    }
}