private void LoadPopupScreen()
            {
                _state = State.Waiting;

                var topScreenInfo = _screenDirector.GetTopLiveScreen();

                if (topScreenInfo != null)
                {
                    topScreenInfo.screen.OnLostFocus();
                }

                _screenDirector.CloseScreenAboveLayer(PriorityLayer.Popup, true, () =>
                {
                    _nextLiveScreenInfo = new LiveScreenInfo()
                    {
                        id     = _screenDirector.NextId(PriorityLayer.Popup),
                        name   = _jobData.name,
                        screen = _screenDirector.CloneScreen(_cachedScreenInfo.screen)
                    };

                    _screenDirector.AddLiveScreenInfo(_nextLiveScreenInfo);
                    _nextLiveScreenInfo.screen.OnCreated(_jobData.obj);
                    _nextLiveScreenInfo.screen.PrepareAnimateIn();
                    _nextLiveScreenInfo.screen.Open(true);
                    _nextLiveScreenInfo.screen.OnStart(_jobData.obj);
                    _nextLiveScreenInfo.screen.OnFocus();
                    _nextLiveScreenInfo.screen.Open(false, () =>
                    {
                        _nextLiveScreenInfo.screen.OnReady();
                        _state = State.End;
                    });
                });
            }
            /// <summary>
            /// Load to display alert screen
            /// </summary>
            private void LoadAlertScreen()
            {
                _state = State.Waiting;

                var topScreenInfo = _screenDirector.GetTopLiveScreen();

                if (topScreenInfo != null)
                {
                    topScreenInfo.screen.OnLostFocus();
                }

                // Create instance of next live screen info to be displayed
                _nextLiveScreenInfo = new LiveScreenInfo()
                {
                    id     = _screenDirector.NextId(PriorityLayer.Alert),
                    name   = _jobData.name,
                    screen = _screenDirector.CloneScreen(_cachedScreenInfo.screen)
                };

                _screenDirector.AddLiveScreenInfo(_nextLiveScreenInfo);
                _nextLiveScreenInfo.screen.OnCreated(_jobData.obj);
                _nextLiveScreenInfo.screen.PrepareAnimateIn();
                _nextLiveScreenInfo.screen.Open(true);
                _nextLiveScreenInfo.screen.OnStart(_jobData.obj);
                _nextLiveScreenInfo.screen.OnFocus();
                _nextLiveScreenInfo.screen.Open(false, () =>
                {
                    _nextLiveScreenInfo.screen.OnReady();
                    _state = State.End;
                });
            }
 public bool Match(LiveScreenInfo other)
 {
     if (other == null)
     {
         return(false);
     }
     return(name == other.name && screen.Layer == other.screen.Layer);
 }
            private void LoadHighScreen()
            {
                _state = State.Waiting;

                var topScreenInfo = _screenDirector.GetTopLiveScreen();

                if (topScreenInfo != null)
                {
                    topScreenInfo.screen.OnLostFocus();
                }

                _screenDirector.CloseScreenAboveLayer(PriorityLayer.Low, true, () =>
                {
                    UnityAction <LiveScreenInfo> act = previousScreen =>
                    {
                        _nextLiveScreenInfo = new LiveScreenInfo()
                        {
                            id     = 1,
                            name   = _jobData.name,
                            screen = _cachedScreenInfo.screen
                        };

                        _screenDirector.AddLiveScreenInfo(_nextLiveScreenInfo);
                        _nextLiveScreenInfo.screen.OnCreated(_jobData.obj);
                        _nextLiveScreenInfo.screen.PrepareAnimateIn();
                        _nextLiveScreenInfo.screen.Open(true);
                        _nextLiveScreenInfo.screen.OnStart(_jobData.obj);
                        _nextLiveScreenInfo.screen.OnFocus();
                        _nextLiveScreenInfo.screen.Open(false, () =>
                        {
                            _nextLiveScreenInfo.screen.OnReady();
                            _state = State.End;
                        });

                        if (previousScreen != null)
                        {
                            CloseScreen(previousScreen.screen, true);
                        }
                    };

                    topScreenInfo = _screenDirector.GetTopLiveScreen();

                    if (topScreenInfo != null)
                    {
                        topScreenInfo.screen.AnimateOut(() => act(topScreenInfo));
                    }
                    else
                    {
                        act(topScreenInfo);
                    }
                });
            }
        private void CloseScreenAboveLayer(PriorityLayer layer, bool quick, UnityAction onFinish)
        {
            var node = _liveScreens.Last;

            if (node == null || node.Value.screen.Layer <= layer)
            {
                if (onFinish != null)
                {
                    onFinish();
                }
            }
            else
            {
                node.Value.screen.Close(quick, () =>
                {
                    var screen = node.Value;
                    LiveScreenInfo lowerScreen = null;

                    if (node.Previous != null)
                    {
                        lowerScreen = node.Previous.Value;
                    }

                    if (screen.Match(lowerScreen))
                    {
                        screen.screen.Destroy();
                    }
                    else
                    {
                        ScreenInfo screenInfo = _screens[screen.name];

                        if (!screen.screen.Equals(screenInfo.screen))
                        {
                            screen.screen.Destroy();
                        }

                        if (!screenInfo.cached)
                        {
                            _screens.Remove(screen.name);
                            screen.screen.Destroy();
                        }
                    }

                    _liveScreens.Remove(node);

                    CloseScreenAboveLayer(layer, quick, onFinish);
                });
            }
        }
        private void AddLiveScreenInfo(LiveScreenInfo data, bool fromLast = true)
        {
            var node = fromLast ? _liveScreens.Last : _liveScreens.First;

            if (fromLast)
            {
                while (true)
                {
                    if (node == null)
                    {
                        _liveScreens.AddFirst(data);
                        break;
                    }
                    if ((int)data.screen.Layer >= (int)node.Value.screen.Layer)
                    {
                        _liveScreens.AddAfter(node, data);
                        break;
                    }
                    node = node.Previous;
                }
            }
            else
            {
                while (true)
                {
                    if (node == null)
                    {
                        _liveScreens.AddFirst(data);
                        break;
                    }
                    if ((int)data.screen.Layer <= (int)node.Value.screen.Layer)
                    {
                        _liveScreens.AddBefore(node, data);
                        break;
                    }
                    node = node.Next;
                }
            }

            OrderScreenSiblings();
        }
        /// <summary>
        /// Close a screen
        /// </summary>
        /// <param name="closedScreen">Screen to be closed</param>
        /// <param name="quick">If true, the screen will be closed quickly. Otherwise, it will be animated to close</param>
        /// <param name="onFinish">Callback after closing is finished</param>
        static public void CloseScreen(Screen closedScreen, bool quick, UnityAction onFinish = null)
        {
            var liveScreens = Instance._liveScreens;
            var node        = liveScreens.Last;

            while (node != null)
            {
                var screen = node.Value;

                if (screen.screen.Equals(closedScreen))
                {
                    screen.screen.Close(quick, () =>
                    {
                        LiveScreenInfo lowerScreen = null;

                        if (node.Next == null && node.Previous != null)
                        {
                            lowerScreen = node.Previous.Value;
                        }

                        screen.screen.OnLostFocus();

                        if (screen.Match(lowerScreen))
                        {
                            screen.screen.Destroy();
                        }
                        else
                        {
                            ScreenInfo screenInfo = Instance._screens[screen.name];

                            if (!screen.screen.Equals(screenInfo.screen))
                            {
                                screen.screen.Destroy();
                            }

                            if (!screenInfo.cached)
                            {
                                Instance._screens.Remove(screen.name);
                                screen.screen.Destroy();
                            }
                        }

                        liveScreens.Remove(node);

                        if (lowerScreen != null)
                        {
                            lowerScreen.screen.OnFocus();
                        }

                        if (onFinish != null)
                        {
                            onFinish();
                        }
                    });
                    return;
                }
                node = node.Previous;
            }

            if (onFinish != null)
            {
                onFinish();
            }
        }
            private void LoadLowScreen()
            {
                _state = State.Waiting;

                var topScreenInfo = _screenDirector.GetTopLiveScreen();

                if (topScreenInfo != null && (topScreenInfo.screen.Layer == PriorityLayer.Alert || topScreenInfo.screen.Layer == PriorityLayer.Popup))
                {
                    topScreenInfo.screen.OnLostFocus();
                }

                _screenDirector.CloseScreenByLayer(_screenDirector._liveScreens.Last, PriorityLayer.Alert | PriorityLayer.Popup, true, () =>
                {
                    topScreenInfo = _screenDirector.GetTopLiveScreen();

                    if (topScreenInfo != null)
                    {
                        if (topScreenInfo.screen.Layer == PriorityLayer.High)
                        {
                            topScreenInfo.screen.OnFocus();

                            if (_screenDirector.IsScreenLive(_cachedScreenInfo.screen))
                            {
                                _nextLiveScreenInfo.screen.PrepareAnimateIn();
                                _nextLiveScreenInfo.screen.Open(true);

                                topScreenInfo.screen.AnimateOut(() =>
                                {
                                    topScreenInfo.screen.OnLostFocus();
                                    CloseScreen(topScreenInfo.screen, true);

                                    _nextLiveScreenInfo.screen.OnStart(_jobData.obj);
                                    _nextLiveScreenInfo.screen.OnFocus();
                                    _nextLiveScreenInfo.screen.Open(false, () =>
                                    {
                                        _nextLiveScreenInfo.screen.OnReady();
                                        _state = State.End;
                                    });
                                });
                            }
                            else
                            {
                                _screenDirector.CloseScreenByLayer(_screenDirector._liveScreens.Last, PriorityLayer.Low, true, () =>
                                {
                                    _nextLiveScreenInfo = new LiveScreenInfo()
                                    {
                                        id     = 1,
                                        name   = _jobData.name,
                                        screen = _cachedScreenInfo.screen
                                    };

                                    _screenDirector.AddLiveScreenInfo(_nextLiveScreenInfo);
                                    _nextLiveScreenInfo.screen.OnCreated(_jobData.obj);
                                    _nextLiveScreenInfo.screen.PrepareAnimateIn();
                                    _nextLiveScreenInfo.screen.Open(true);

                                    topScreenInfo.screen.AnimateOut(() =>
                                    {
                                        topScreenInfo.screen.OnLostFocus();
                                        CloseScreen(topScreenInfo.screen, true);

                                        _nextLiveScreenInfo.screen.OnStart(_jobData.obj);
                                        _nextLiveScreenInfo.screen.OnFocus();
                                        _nextLiveScreenInfo.screen.Open(false, () =>
                                        {
                                            _nextLiveScreenInfo.screen.OnReady();
                                            _state = State.End;
                                        });
                                    });
                                });
                            }
                            return;
                        }
                    }

                    if (_screenDirector.IsScreenLive(_cachedScreenInfo.screen))
                    {
                        _cachedScreenInfo.screen.PrepareAnimateIn();
                        _cachedScreenInfo.screen.OnStart(_jobData.obj);
                        _cachedScreenInfo.screen.OnFocus();
                        _cachedScreenInfo.screen.Open(false, () =>
                        {
                            _nextLiveScreenInfo.screen.OnReady();
                            _state = State.End;
                        });
                    }
                    else
                    {
                        _nextLiveScreenInfo = new LiveScreenInfo()
                        {
                            id     = 1,
                            name   = _jobData.name,
                            screen = _cachedScreenInfo.screen
                        };

                        _screenDirector.AddLiveScreenInfo(_nextLiveScreenInfo, false);
                        _nextLiveScreenInfo.screen.OnCreated(_jobData.obj);
                        _nextLiveScreenInfo.screen.PrepareAnimateIn();
                        _nextLiveScreenInfo.screen.Open(true);

                        if (topScreenInfo != null)
                        {
                            topScreenInfo.screen.AnimateOut(() =>
                            {
                                topScreenInfo.screen.OnLostFocus();
                                CloseScreen(topScreenInfo.screen, true);

                                _nextLiveScreenInfo.screen.OnStart(_jobData.obj);
                                _nextLiveScreenInfo.screen.OnFocus();
                                _nextLiveScreenInfo.screen.Open(false, () =>
                                {
                                    _nextLiveScreenInfo.screen.OnReady();
                                    _state = State.End;
                                });
                            });
                        }
                        else
                        {
                            _nextLiveScreenInfo.screen.OnStart(_jobData.obj);
                            _nextLiveScreenInfo.screen.OnFocus();
                            _nextLiveScreenInfo.screen.Open(false, () =>
                            {
                                _nextLiveScreenInfo.screen.OnReady();
                                _state = State.End;
                            });
                        }
                    }
                });
            }