int FindFirstMatchingRawSampleIndexInScopeRecursively(RawFrameDataView frameData, ref List <int> sampleIndexPath, string sampleName, int sampleMarkerId = FrameDataView.invalidMarkerId)
        {
            if (sampleMarkerId == FrameDataView.invalidMarkerId)
            {
                sampleMarkerId = frameData.GetMarkerId(sampleName);
            }
            var firstIndex = sampleIndexPath != null && sampleIndexPath.Count > 0 ? sampleIndexPath[sampleIndexPath.Count - 1] : 0;
            var lastSampleInSearchScope = firstIndex == 0 ? frameData.sampleCount - 1 : firstIndex + frameData.GetSampleChildrenCountRecursive(firstIndex);

            // Check if the enclosing scope matches the searched sample
            if (sampleIndexPath != null && sampleIndexPath.Count > 0 && (sampleMarkerId == FrameDataView.invalidMarkerId && GetItemName(frameData, firstIndex) == sampleName || frameData.GetSampleMarkerId(firstIndex) == sampleMarkerId))
            {
                return(firstIndex);
            }

            var samplePathAndLastSampleInScope = new List <RawSampleIterationInfo>()
            {
            };

            for (int i = firstIndex; i <= lastSampleInSearchScope; i++)
            {
                samplePathAndLastSampleInScope.Add(new RawSampleIterationInfo {
                    sampleIndex = i, lastSampleIndexInScope = i + frameData.GetSampleChildrenCountRecursive(i)
                });
                if (sampleMarkerId == FrameDataView.invalidMarkerId && (sampleName != null && GetItemName(frameData, i) == sampleName) || frameData.GetSampleMarkerId(i) == sampleMarkerId)
                {
                    // ignore the first sample if it's the enclosing sample (which is already in the list)
                    for (int j = sampleIndexPath.Count > 0 ? 1 : 0; j < samplePathAndLastSampleInScope.Count; j++)
                    {
                        // ignore the first sample if it's either the thread root sample.
                        // we can't always assume that there is a thread root sample, as the data may be mal formed, but we need to check if this is one by checking the name
                        if (j == 0 && frameData.GetSampleName(samplePathAndLastSampleInScope[j].sampleIndex) == frameData.threadName)
                        {
                            continue;
                        }
                        sampleIndexPath.Add(samplePathAndLastSampleInScope[j].sampleIndex);
                    }
                    return(i);
                }
                while (samplePathAndLastSampleInScope.Count > 0 && i + 1 > samplePathAndLastSampleInScope[samplePathAndLastSampleInScope.Count - 1].lastSampleIndexInScope)
                {
                    samplePathAndLastSampleInScope.RemoveAt(samplePathAndLastSampleInScope.Count - 1);
                }
            }
            return(RawFrameDataView.invalidSampleIndex);
        }