private NativeArray <PathNode> GridToNative(int2 endPosition)
    {
        GridData[,] grid = grid_map.Instance.Grid;
        NativeArray <PathNode> pathNodeArray = new NativeArray <PathNode>(grid.GetLength(0) * grid.GetLength(1), Allocator.TempJob);

        for (int x = 0; x < grid.GetLength(0); x++)
        {
            for (int y = 0; y < grid.GetLength(1); y++)
            {
                PathNode pathNode = new PathNode();
                pathNode.x     = x;
                pathNode.y     = y;
                pathNode.index = CalculateIndex(x, y, grid.GetLength(0));
                pathNode.costG = int.MaxValue;
                pathNode.costH = CalculateDistanceCost(new int2(x, y), endPosition);
                pathNode.CalculateCostF();
                pathNode.isWalkable           = grid[x, y].IsWalkable;
                pathNode.weight               = grid[x, y].Weight;
                pathNode.indexPrev            = -1;
                pathNodeArray[pathNode.index] = pathNode;
            }
        }
        return(pathNodeArray);
    }
        public void Execute()
        {
            // // * testing
            // int2 gridSize = new int2(134, 98);
            // NativeArray<PathNode> pathNodeArray = new NativeArray<PathNode>(gridSize.x * gridSize.y, Allocator.Temp);
            // for (int x = 0; x < gridSize.x; x++)
            // {
            //     for (int y = 0; y < gridSize.y; y++)
            //     {
            //         PathNode pathNode = new PathNode();
            //         pathNode.x = x;
            //         pathNode.y = y;
            //         pathNode.index = CalculateIndex(x, y, gridSize.x);
            //         pathNode.costG = int.MaxValue;
            //         pathNode.costH = CalculateDistanceCost(new int2(x, y), endPosition);
            //         pathNode.CalculateCostF();
            //         pathNode.isWalkable = true;
            //         // pathNode.weight = ?;
            //         pathNode.indexPrev = -1;
            //         pathNodeArray[pathNode.index] = pathNode;
            //     }
            // }
            // // * testing
            // PathNode walkablePathNode = pathNodeArray[CalculateIndex(1, 0, gridSize.x)];
            // walkablePathNode.SetIsWalkable(false);
            // pathNodeArray[CalculateIndex(1, 0, gridSize.x)] = walkablePathNode;
            // walkablePathNode = pathNodeArray[CalculateIndex(1, 1, gridSize.x)];
            // walkablePathNode.SetIsWalkable(false);
            // pathNodeArray[CalculateIndex(1, 1, gridSize.x)] = walkablePathNode;
            // walkablePathNode = pathNodeArray[CalculateIndex(1, 2, gridSize.x)];
            // walkablePathNode.SetIsWalkable(false);
            // pathNodeArray[CalculateIndex(1, 2, gridSize.x)] = walkablePathNode;
            // // burst incompatible
            // NativeArray<int2> neighbourOffsetArray = new NativeArray<int2>(new int2[] {
            //     new int2(-1, 0),    // L
            //     new int2(+1, 0),    // R
            //     new int2(0, -1),    // D
            //     new int2(0, +1),    // U
            //     new int2(-1, -1),   // LD
            //     new int2(-1, +1),   // LU
            //     new int2(+1, -1),   // RD
            //     new int2(+1, +1),   // DU
            // }, Allocator.Temp);
            // burst compatible
            NativeArray <int2> neighbourOffsetArray = new NativeArray <int2>(8, Allocator.Temp);

            neighbourOffsetArray[0] = new int2(-1, 0);  // L
            neighbourOffsetArray[1] = new int2(+1, 0);  // R
            neighbourOffsetArray[2] = new int2(0, -1);  // D
            neighbourOffsetArray[3] = new int2(0, +1);  // U
            neighbourOffsetArray[4] = new int2(-1, -1); // LD
            neighbourOffsetArray[5] = new int2(-1, +1); // LU
            neighbourOffsetArray[6] = new int2(+1, -1); // RD
            neighbourOffsetArray[7] = new int2(+1, +1); // DU
            int      endNodeIndex = CalculateIndex(endPosition.x, endPosition.y, size.x);
            PathNode startNode    = pathNodeArray[CalculateIndex(startPosition.x, startPosition.y, size.x)];

            startNode.costG = 0;
            startNode.CalculateCostF();
            pathNodeArray[startNode.index] = startNode;
            NativeList <int> listOpen   = new NativeList <int>(Allocator.Temp);
            NativeList <int> listClosed = new NativeList <int>(Allocator.Temp);

            listOpen.Add(startNode.index);
            while (listOpen.Length > 0)
            {
                int      currentNodeIndex = GetLowestCostFNodeIndex(listOpen, pathNodeArray);
                PathNode currentNode      = pathNodeArray[currentNodeIndex];
                if (currentNodeIndex == endNodeIndex)
                {
                    // reached end
                    break;
                }
                // remove current node from open list
                for (int i = 0; i < listOpen.Length; i++)
                {
                    if (listOpen[i] == currentNodeIndex)
                    {
                        listOpen.RemoveAtSwapBack(i);
                        break;
                    }
                }
                listClosed.Add(currentNodeIndex);
                for (int i = 0; i < neighbourOffsetArray.Length; i++)
                {
                    int2 neighbourOffset   = neighbourOffsetArray[i];
                    int2 neighbourPosition = new int2(currentNode.x + neighbourOffset.x, currentNode.y + neighbourOffset.y);
                    if (!IsPositionInsideGrid(neighbourPosition, size))
                    {
                        // neighbour not valid position
                        continue;
                    }
                    int neighbourNodeIndex = CalculateIndex(neighbourPosition.x, neighbourPosition.y, size.x);
                    if (listClosed.Contains(neighbourNodeIndex))
                    {
                        // already searched this node
                        continue;
                    }
                    PathNode neighbourNode = pathNodeArray[neighbourNodeIndex];
                    if (!neighbourNode.isWalkable)
                    {
                        // not walkable
                        continue;
                    }
                    // diagonal neighbour
                    if (Mathf.Abs(neighbourOffset[0]) + Mathf.Abs(neighbourOffset[1]) > 1)
                    {
                        // corners blocked
                        if (!(pathNodeArray[CalculateIndex(neighbourPosition.x, currentNode.y, size.x)].isWalkable || pathNodeArray[CalculateIndex(currentNode.x, neighbourPosition.y, size.x)].isWalkable))
                        {
                            continue;
                        }
                    }
                    int2 currentNodePosition = new int2(currentNode.x, currentNode.y);
                    int  tentativeCostG      = currentNode.costG + CalculateDistanceCost(currentNodePosition, neighbourPosition) + neighbourNode.weight;
                    // if (tentativeCostG < neighbourNode.costG)
                    if (tentativeCostG < neighbourNode.costG || !listOpen.Contains(neighbourNodeIndex))
                    {
                        neighbourNode.indexPrev = currentNodeIndex;
                        neighbourNode.costG     = tentativeCostG;
                        neighbourNode.CalculateCostF();
                        pathNodeArray[neighbourNodeIndex] = neighbourNode;
                        if (!listOpen.Contains(neighbourNode.index))
                        {
                            listOpen.Add(neighbourNode.index);
                        }
                    }
                }
            }
            PathNode endNode = pathNodeArray[endNodeIndex];

            if (endNode.indexPrev == -1)
            {
                // path NOT found
                // print("het");
            }
            else
            {
                // path found
                // path = PathCalculate(pathNodeArray, endNode);
                PathCalculate(pathNodeArray, endNode);
                // NativeList<int2> path = PathCalculate(pathNodeArray, endNode);
                // // * testing
                // foreach (int2 pathPosition in path)
                // {
                //     Debug.Log(pathPosition);
                // }
                // path.Dispose();
            }
            neighbourOffsetArray.Dispose();
            listOpen.Dispose();
            listClosed.Dispose();
        }