public void SendMakeSpell()
    {
        while (_isListeningThreadReading) ;

        _isMainThreadReading = true;
        NetworkUtils.WriteInt(4, _tcpClient.GetStream());
        NetworkUtils.WriteRunicBoard(RunicBoardManager.GetInstance().GetBoardPlayer(), _tcpClient.GetStream());
        _tcpClient.GetStream().Flush();


        int id;
        do
        {
            id = NetworkUtils.ReadInt(_tcpClient.GetStream());
        }
        while (ReadMessage(id));


        if (id == 5)
        {
            SendBoardResponse sbr = new SendBoardResponse(NetworkUtils.ReadBool(_tcpClient.GetStream()), NetworkUtils.ReadBool(_tcpClient.GetStream()));
        }
        _isMainThreadReading = false;
    }
    public SendBoardResponse SendBoard(bool removeActionPoint = true)
    {

        while (_isListeningThreadReading) ;

        _isMainThreadReading = true;
        Logger.Debug("send board");
        NetworkUtils.WriteInt(2, _tcpClient.GetStream());
        NetworkUtils.WriteRunicBoard(RunicBoardManager.GetInstance().GetBoardPlayer(), _tcpClient.GetStream());
        NetworkUtils.WriteBool(removeActionPoint, _tcpClient.GetStream());
        _tcpClient.GetStream().Flush();

        int id;
        do
        {
            id = NetworkUtils.ReadInt(_tcpClient.GetStream());
        }
        while (ReadMessage(id)) ;
        

        if (id == 3)
        {
            SendBoardResponse sbr;
            bool ifExist = NetworkUtils.ReadBool(_tcpClient.GetStream());
            if (ifExist)
            {
                Logger.Debug("spell exist");
                sbr = new SendBoardResponse(ifExist, NetworkUtils.ReadBool(_tcpClient.GetStream()),
                                                                //min range max range 
                                                                NetworkUtils.ReadInt(_tcpClient.GetStream()), NetworkUtils.ReadInt(_tcpClient.GetStream()),
                                                               // isPiercing and isEnemyTargetable
                                                               NetworkUtils.ReadBool(_tcpClient.GetStream()), NetworkUtils.ReadBool(_tcpClient.GetStream()),
                                                               //orientation 
                                                               NetworkUtils.ReadOrientation(_tcpClient.GetStream()),
                                                               //area
                                                               NetworkUtils.ReadArea(_tcpClient.GetStream()));
                sbr._updateArea = true;
                Logger.Debug("update panel spell details");
                UIManager.GetInstance().ShowPanelNoStack("panelSpellDetails");
                UIManager.GetInstance().ShowPanelNoStack("panelArea");

            }
            else
            {
                sbr = new SendBoardResponse(ifExist, NetworkUtils.ReadBool(_tcpClient.GetStream()));
                UIManager.GetInstance().HidePanelNoStack("panelSpellDetails");
                UIManager.GetInstance().HidePanelNoStack("panelArea");
            }
                
            
            _isMainThreadReading = false;
            return sbr;
        }

        else
        {
            _isMainThreadReading = false;
            return null;
        }
        
    }
    void InputUpdate()
    {
        // If mouse is pressed, check if a rune is underneath. If a rune is found, put his gameObject in _heldRune.
        if (Input.GetMouseButtonDown(0))
        {
            Ray camRay = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hitInfo;
            if(Physics.Raycast(camRay, out hitInfo, Mathf.Infinity, LayerMask.GetMask("Runes")))
            {
                _heldRune = hitInfo.collider.gameObject;
                RuneBehaviour runeBehaviour = hitInfo.collider.gameObject.GetComponent<RuneBehaviour>();
                if (runeBehaviour != null)
                {
                    runeBehaviour._state = RuneBehaviour.State.BeingTaken;
                }
            }
        }

        if (Input.GetMouseButtonUp(0) && _heldRune != null)
        {
            Ray camRay = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hitInfo;

            RuneBehaviour runeBehaviour = _heldRune.GetComponent<RuneBehaviour>();
            
            if (Physics.Raycast(camRay, out hitInfo, Mathf.Infinity, LayerMask.GetMask("Runes Slot")) && !ClientManager.GetInstance()._client.LockedMode)
            {
                    RuneSlotBehaviour runeSlotBehaviour = hitInfo.collider.gameObject.GetComponent<RuneSlotBehaviour>();
                if (runeSlotBehaviour != null)
                {
                    Rune rune = _heldRune.GetComponent<RuneBehaviour>()._rune;
                    int slotPosition = runeSlotBehaviour._position;
                    // Rune is currently on board
                    if (rune.IsOnBoard())
                    {
                        // Rune is released on board
                        if(runeSlotBehaviour.isBoard)
                        {
                            Logger.Debug("BOARD");
                            if (Board.ChangeRunePosition(rune.PositionOnBoard, slotPosition))
                            {
                                _heldRune.transform.SetParent(hitInfo.collider.transform);
                            }
                        }
                        // Rune is released in hand
                        else
                        {                            
                            Logger.Debug("HAND");
                            if (_board.RemoveRuneFromBoard(rune.PositionOnBoard))
                            {
                                Transform hand = hitInfo.collider.transform.parent;
                                Transform slot = hand.GetChild(rune.PositionInHand);
                                _heldRune.transform.SetParent(slot);
                                LatestSendBoardResponse = ClientManager.GetInstance()._client.SendBoard(false);
                            }
                        }
                    }
                    // Rune is currently in hand
                    else if (runeSlotBehaviour.isBoard)
                    {
                        int newPositionOnBoard = Board.PlaceRuneOnBoard(rune.PositionInHand, slotPosition);
                        if (newPositionOnBoard >= 0)
                        {
                             LatestSendBoardResponse =  ClientManager.GetInstance()._client.SendBoard();
                             if(LatestSendBoardResponse._exist)
                             {
                                 Transform parent;
                                 if (newPositionOnBoard == 12)
                                 {
                                     parent = _boardGO.transform.GetChild(9).transform;
                                 }
                                 else
                                 {
                                     parent = hitInfo.collider.transform;
                                 }
                                 _heldRune.transform.SetParent(parent);
                             }
                             else
                             {
                                 Board.RemoveRuneFromBoard(slotPosition, false);
                             }
                        }
                    }
                }
            }
            
            runeBehaviour._state = RuneBehaviour.State.BeingReleased;
            _heldRune = null;
        }
    }