/// <summary>
        /// On register mediator
        /// </summary>
        public override void OnRegister()
        {
            InitAttackLineSignal.AddListener(isActive =>
            {
                View.SetActive(isActive);
            });

            SetAttackLinePosSignal.AddListener(posStruct =>
            {
                View.SetLinePosition(posStruct.StartPos, posStruct.EndPos);
            });
        }
        private void InitApplyTrate()
        {
            if (View.Side != BattleArena.ActiveSide)
            {
                return;
            }
            var tempHasApplyed = !View.HasApplied;

            View.HasApplied        = tempHasApplyed;
            BattleArena.ApplyTrate = tempHasApplyed ? View : null;
            InitAttackLineSignal.Dispatch(tempHasApplyed);
        }
        /// <summary>
        /// On apply trate
        /// </summary>
        private void OnApplyTrate()
        {
            if (View.Side != BattleArena.ActiveSide ||
                View.Card.Status != BattleStatus.Sleep && View.Card.Status != BattleStatus.Active)
            {
                BattleArena.ApplyTrate.HasApplied = false;
                BattleArena.ApplyTrate            = null;
                InitAttackLineSignal.Dispatch(false);
                return;
            }

            AddTrateToCardSignal.Dispatch(View, BattleArena.ApplyTrate);
        }
        /// <summary>
        /// On init attack
        /// </summary>
        private void OnInitAttack()
        {
            if (View.Side != BattleArena.ActiveSide || !View.HasActive)
            {
                BattleArena.AttackUnit = null;
                return;
            }

            var tempHasAttack = !View.HasAttack;

            View.HasAttack         = tempHasAttack;
            BattleArena.AttackUnit = tempHasAttack ? View : null;
            InitAttackLineSignal.Dispatch(tempHasAttack);
        }
        /// <summary>
        /// Set attack line position
        /// </summary>
        /// <param name="startPos"></param>
        /// <param name="endPos"></param>
        public void SetLinePosition(Vector3 startPos, Vector3 endPos)
        {
            endPos = new Vector3(endPos.x, endPos.y, 0);
            _line.SetPosition(0, startPos);
            _line.SetPosition(1, endPos);
            _headImage.transform.position = endPos;

            const float padding = 0.4f;

            if (BattleArena.ActiveSide == BattleSide.Player)
            {
                // get rotate angle
                var angle = AngleBetweenVector2(new Vector2(startPos.x, startPos.y - padding), endPos);
                // rotate cursor
                _headImage.transform.rotation = Quaternion.Euler(0, 0, angle - 90);
                // check attack line area
                if (!(angle < 0) || BattleArena.AttackUnit == null || !BattleArena.AttackUnit.HasAttack)
                {
                    return;
                }
                BattleArena.AttackUnit.HasAttack = false;
                BattleArena.AttackUnit           = null;
                InitAttackLineSignal.Dispatch(false);
            }
            else
            {
                // get rotate angle
                var angle = AngleBetweenVector2(new Vector2(startPos.x, startPos.y + padding), endPos);
                // rotate cursor
                _headImage.transform.rotation = Quaternion.Euler(0, 0, angle - 90);
                // check attack line area
                if (!(angle > 0) || BattleArena.AttackUnit == null || !BattleArena.AttackUnit.HasAttack)
                {
                    return;
                }
                BattleArena.AttackUnit.HasAttack = false;
                BattleArena.AttackUnit           = null;
                InitAttackLineSignal.Dispatch(false);
            }
        }