void Awake()
    {
        EventManager.instance.onModeChanged += ResetLastClickedTile;

        instance   = this;
        gridWidth  = MapSizeController.mapSize;
        gridHeight = MapSizeController.mapSize;
        grid       = new GridXZ(gridWidth, gridHeight, cellSize, Vector3.zero);

        // Create ground visual
        float groundSizeX = gridWidth * cellSize;
        float groundSizeY = gridHeight * cellSize;

        ground = Instantiate(groundVisualPrefab, new Vector3(groundSizeX / 2, -0.5f, groundSizeY / 2),
                             Quaternion.identity);
        ground.localScale = new Vector3(groundSizeX, 1, groundSizeY);

        selectedBuildingSO      = null;
        currentBuildingRotation = BuildingTypeSO.Direction.Down;

        float spawnChance = 0.05f; // The spawning chance of the trees when the game starts

        for (int i = 0; i < gridWidth; i++)
        {
            for (int j = 0; j < gridHeight; j++)
            {
                float randFloat = Random.Range(0f, 1f);
                if (randFloat < spawnChance)
                {
                    spawnTree(i, j);
                }
            }
        }
    }
    public void spawnTree(int x, int z)
    {
        int randTree = Random.Range(1, 4);

        BuildingTypeSO.Direction rotation     = BuildingTypeSO.Direction.Down;
        List <Vector2Int>        positionList = new List <Vector2Int>();

        positionList.Add(new Vector2Int(0, 0));
        Vector2Int rotationOffset;
        Vector3    worldPosition;
        Building   placedBuilding;

        switch (randTree)
        {
        case 1:
            rotationOffset = treeOne.GetRotationOffset(BuildingTypeSO.Direction.Down);
            worldPosition  = grid.GetWorldPosition(x, z) +
                             new Vector3(rotationOffset.x, 0, rotationOffset.y) * grid.GetCellSize();
            placedBuilding =
                Building.SpawnBuilding(worldPosition, new Vector2Int(x, z), rotation, treeOne, positionList);
            grid.GetCell(x, z).SetBuilding(placedBuilding);
            placedBuildings.Add(placedBuilding);
            break;

        case 2:
            rotationOffset = treeTwo.GetRotationOffset(BuildingTypeSO.Direction.Down);
            worldPosition  = grid.GetWorldPosition(x, z) +
                             new Vector3(rotationOffset.x, 0, rotationOffset.y) * grid.GetCellSize();
            placedBuilding =
                Building.SpawnBuilding(worldPosition, new Vector2Int(x, z), rotation, treeTwo, positionList);
            grid.GetCell(x, z).SetBuilding(placedBuilding);
            placedBuildings.Add(placedBuilding);
            break;

        case 3:
            rotationOffset = treeThree.GetRotationOffset(BuildingTypeSO.Direction.Down);
            worldPosition  = grid.GetWorldPosition(x, z) +
                             new Vector3(rotationOffset.x, 0, rotationOffset.y) * grid.GetCellSize();
            placedBuilding = Building.SpawnBuilding(worldPosition, new Vector2Int(x, z), rotation, treeThree,
                                                    positionList);
            grid.GetCell(x, z).SetBuilding(placedBuilding);
            placedBuildings.Add(placedBuilding);
            break;
        }
    }
    void Update()
    {
        if (!EventSystem.current.IsPointerOverGameObject())
        {
            if (currentMode == ClickMode.Normal)
            {
                // Select placed building
                if (Input.GetMouseButtonDown(0) && selectedBuildingSO == null)
                {
                    if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out RaycastHit hitInfo,
                                        1000f,
                                        (1 << 9)))
                    {
                        if (!EventSystem.current.IsPointerOverGameObject())
                        {
                            InspectorMenu.instance.DisplayDetails(hitInfo.collider.transform.parent
                                                                  .GetComponent <Attraction>());
                        }
                    }
                }

                if (Input.GetMouseButtonDown(1))
                {
                    SetSelectedBuildingType(null);
                }

                // Place building
                if (selectedBuildingSO != null && Input.GetMouseButtonDown(0))
                {
                    PlaceBuilding();
                }

                // Hide preview if not enough money
                if (Input.GetMouseButtonUp(0) && selectedBuildingSO != null &&
                    GameManager.instance.Money < selectedBuildingSO.price)
                {
                    SetSelectedBuildingType(null);
                }

                // Rotate building
                if (Input.GetKeyDown(KeyCode.R))
                {
                    currentBuildingRotation = BuildingTypeSO.GetNextDirectionLeft(currentBuildingRotation);
                }
                else if (Input.GetKeyDown(KeyCode.F))
                {
                    currentBuildingRotation = BuildingTypeSO.GetNextDirectionRight(currentBuildingRotation);
                }

                if (Input.GetKeyDown(KeyCode.Escape))
                {
                    SetSelectedBuildingType(null);
                }

                if (Input.GetKeyDown(KeyCode.B))
                {
                    SetSelectedBuildingType(null);
                }
            }
            else if (currentMode == ClickMode.Destroy)
            {
                int x, z;
                grid.XZFromWorldPosition(GetMouseWorldPosition(), out x, out z);
                if (Input.GetMouseButton(0))
                {
                    if (selectedBuildingSO == null)
                    {
                        if ((lastX != x) || (lastZ != z))
                        {
                            lastX = x;
                            lastZ = z;
                            SellBuilding();
                        }
                    }
                    else
                    {
                        SetSelectedBuildingType(null);
                    }
                }

                if (Input.GetMouseButtonUp(0))
                {
                    ResetLastClickedTile(ClickMode.Destroy);
                }

                if (Input.GetMouseButtonDown(1))
                {
                    SetSelectedBuildingType(null);
                    GameManager.instance.SwitchMode();
                    EventManager.instance.ModeChanged(currentMode);
                }

                if (Input.GetKeyUp(KeyCode.Escape))
                {
                    SetSelectedBuildingType(null);
                    GameManager.instance.SwitchMode();
                    EventManager.instance.ModeChanged(currentMode);
                }

                if (Input.GetKeyDown(KeyCode.B))
                {
                    SetSelectedBuildingType(null);
                    GameManager.instance.SwitchMode();
                    EventManager.instance.ModeChanged(currentMode);
                }
            }
            else if (currentMode == ClickMode.Road)
            {
                if (selectedBuildingSO != null && Input.GetMouseButton(0) &&
                    selectedBuildingSO.type == BuildingTypeSO.Type.Road)
                {
                    int x, z;
                    grid.XZFromWorldPosition(GetMouseWorldPosition(), out x, out z);
                    if (grid.GetCell(x, z) == null)
                    {
                        return;
                    }
                    if (grid.GetCell(x, z).GetBuilding() != null)
                    {
                        return;
                    }
                    if ((lastX != x) || (lastZ != z))
                    {
                        if (grid.GetCell(x, z).GetBuilding() == null)
                        {
                            GameManager.instance.BuyBuilding(roadStraight);
                        }

                        lastX = x;
                        lastZ = z;
                        UpdateRoad(x, z);
                        foreach (Cell cell in grid.GetCell(x, z).Neighbours)
                        {
                            if (cell.GetBuilding() != null && cell.GetBuilding().Type.type == BuildingTypeSO.Type.Road)
                            {
                                UpdateRoad(cell.GetX(), cell.GetY());
                            }
                        }
                    }
                }

                if (Input.GetMouseButtonUp(0))
                {
                    EventManager.instance.MapChanged();
                }

                if (Input.GetMouseButton(0) && selectedBuildingSO != null &&
                    GameManager.instance.Money < selectedBuildingSO.price)
                {
                    SetSelectedBuildingType(null);
                    GameManager.instance.SwitchRoadMode();
                    EventManager.instance.ModeChanged(currentMode);
                }

                if (Input.GetMouseButtonDown(1))
                {
                    SetSelectedBuildingType(null);
                    GameManager.instance.SwitchRoadMode();
                    EventManager.instance.ModeChanged(currentMode);
                }

                if (Input.GetKeyUp(KeyCode.Escape))
                {
                    SetSelectedBuildingType(null);
                    GameManager.instance.SwitchRoadMode();
                    EventManager.instance.ModeChanged(currentMode);
                }

                if (Input.GetKeyDown(KeyCode.B))
                {
                    SetSelectedBuildingType(null);
                    GameManager.instance.SwitchRoadMode();
                    EventManager.instance.ModeChanged(currentMode);
                }
            }
        }
    }
    Road ChangeRoadDirection(BuildingTypeSO road, BuildingTypeSO.Direction rotation, int x, int z)
    {
        Cell currentCell = grid.GetCell(x, z);
        List <Vector2Int> positionList = road.GetPositionList(new Vector2Int(x, z), rotation);

        if (currentCell.GetBuilding() != null && currentCell.GetBuilding().Type.type == BuildingTypeSO.Type.Road)
        {
            Road tmp = (Road)currentCell.GetBuilding();
            tmp.roadS.SetActive(false);
            tmp.roadL.SetActive(false);
            tmp.roadT.SetActive(false);
            tmp.roadX.SetActive(false);

            switch (rotation)
            {
            case BuildingTypeSO.Direction.Down:
                break;

            case BuildingTypeSO.Direction.Left:
                break;

            case BuildingTypeSO.Direction.Up:
                break;

            case BuildingTypeSO.Direction.Right:
                break;
            }
        }

        // Check if all coordinates are empty
        bool canBuild = true;

        foreach (Vector2Int gridPosition in positionList)
        {
            // If any of the cells is occupied, don't build:c
            try
            {
                if (!grid.GetCell(gridPosition.x, gridPosition.y).IsEmpty())
                {
                    canBuild = false;
                    break;
                }
            }
            catch (NotValidCellException e)
            {
                canBuild = false;
            }
        }

        // Place building if area is clear
        if (canBuild)
        {
            Vector2Int rotationOffset = road.GetRotationOffset(rotation);
            Vector3    worldPosition  = grid.GetWorldPosition(x, z) +
                                        new Vector3(rotationOffset.x, 0, rotationOffset.y) * grid.GetCellSize();
            Building placedBuilding =
                Building.SpawnBuilding(worldPosition, new Vector2Int(x, z), rotation, road, positionList);

            foreach (Vector2Int gridPositions in positionList)
            {
                grid.GetCell(gridPositions.x, gridPositions.y).SetBuilding(placedBuilding);
            }

            if (!Input.GetMouseButton(0))
            {
                SetSelectedBuildingType(null);
            }

            placedBuildings.Add(placedBuilding);
            return((Road)placedBuilding);
        }

        return(null);
    }