public ComponentRenderer(IComponent component, WebViewRenderer webViewRenderer, ComponentRenderer parent = null)
 {
     Component       = component;
     WebViewRenderer = webViewRenderer;
     Parent          = parent;
     InitialNode     = parent?.CurrentNode ?? -1;
     if (parent != null)
     {
         parent.Children.Add(this);
         //foreach(var sequence in parent.Sequences.Reverse())
         //{
         //    Sequences.Push(sequence);
         //}
     }
 }
        public async Task <string> AddComponent(Type componentType, Action <object> parameterSetter)
        {
            ComponentRenderer adapter = null;
            await Dispatcher.InvokeAsync(async() =>
            {
                var component   = InstantiateComponent(componentType);
                var componentId = AssignRootComponentId(component);
                parameterSetter?.Invoke(component);

                adapter = new ComponentRenderer(component, this);
                Renderers[componentId] = adapter;
                try
                {
                    await RenderRootComponentAsync(componentId).ConfigureAwait(false);
                }catch (Exception e)
                {
                }
            }).ConfigureAwait(false);

            return(DOMBuilder.ToString());
        }
        void ProcessTree(RenderTreeEdit edit, RenderBatch batch, int startIndex, int subLength)
        {
            for (int i = 0; i < subLength; i++)
            {
                int currentIndex = startIndex + i;
                var frame        = batch.ReferenceFrames.Array[currentIndex];
                switch (edit.Type)
                {
                case RenderTreeEditType.PrependFrame:
                {
                    switch (frame.FrameType)
                    {
                    case RenderTreeFrameType.Component:
                    {
                        CurrentNode = WebViewRenderer.DOMBuilder.CreateMarkerElement(CurrentNode, frame.Sequence, frame.Component.GetType().Name);
                        //Sequences.Push(frame.Sequence);
                        var childRenderer = new ComponentRenderer(frame.Component, WebViewRenderer, this);
                        WebViewRenderer.Renderers[frame.ComponentId] = childRenderer;
                        //we dont need to process the subtree of components as the Renderer will process it again
                        //ProcessTree(edit, batch, currentIndex + 1, frame.ElementSubtreeLength - 1);
                        i += frame.ComponentSubtreeLength - 1;
                        //Sequences.Pop();
                        CurrentNode = WebViewRenderer.DOMBuilder.Parent(CurrentNode);
                    }
                    break;

                    case RenderTreeFrameType.Element:
                    {
                        CurrentNode = WebViewRenderer.DOMBuilder.CreateElement(CurrentNode, frame.Sequence, frame.ElementName);
                        //Sequences.Push(frame.Sequence);
                        ProcessTree(edit, batch, currentIndex + 1, frame.ElementSubtreeLength - 1);
                        i += frame.ElementSubtreeLength - 1;
                        //Sequences.Pop();
                        CurrentNode = WebViewRenderer.DOMBuilder.Parent(CurrentNode);
                    }
                    break;

                    case RenderTreeFrameType.Attribute:
                    {
                        if (frame.AttributeValue is EventCallback callback)
                        {
                            WebViewRenderer.DOMBuilder.SetEvent(CurrentNode, frame.Sequence, frame.AttributeName, callback, frame.AttributeEventUpdatesAttributeName);
                        }
                        else
                        {
                            WebViewRenderer.DOMBuilder.SetAttribute(CurrentNode, frame.Sequence, frame.AttributeName, frame.AttributeValue);
                        }
                    }
                    break;

                    case RenderTreeFrameType.Text:
                        WebViewRenderer.DOMBuilder.InsertText(CurrentNode, frame.Sequence, frame.TextContent);
                        break;

                    case RenderTreeFrameType.Markup:
                    {
                        WebViewRenderer.DOMBuilder.InsertMarkup(CurrentNode, frame.Sequence, frame.MarkupContent);
                    }
                    break;

                    case RenderTreeFrameType.Region:
                    {
                        CurrentNode = WebViewRenderer.DOMBuilder.CreateMarkerElement(CurrentNode, frame.Sequence, frame.AttributeName);
                        //Sequences.Push(frame.Sequence);
                        ProcessTree(edit, batch, currentIndex + 1, frame.RegionSubtreeLength - 1);
                        i += frame.RegionSubtreeLength - 1;
                        //Sequences.Pop();
                        CurrentNode = WebViewRenderer.DOMBuilder.Parent(CurrentNode);
                    }
                    break;

                    case RenderTreeFrameType.ElementReferenceCapture:
                        ElementReference reference = new ElementReference(CurrentNode.ToString());
                        //WebViewRenderer.DOMBuilder.Reference();
                        frame.ElementReferenceCaptureAction(reference);
                        break;

                    case RenderTreeFrameType.None:
                        break;

                    default:
                        throw new NotImplementedException($"Invalid Frame type: {frame.FrameType}");
                    }
                }
                break;

                case RenderTreeEditType.UpdateText:
                {
                    WebViewRenderer.DOMBuilder.UpdateText(CurrentNode, frame.Sequence, frame.TextContent);
                }
                break;

                case RenderTreeEditType.RemoveFrame:
                {
                    WebViewRenderer.DOMBuilder.RemoveAt(CurrentNode, edit.SiblingIndex);
                }
                break;

                case RenderTreeEditType.UpdateMarkup:
                {
                    WebViewRenderer.DOMBuilder.UpdateMarkup(CurrentNode, frame.Sequence, frame.TextContent);
                }
                break;

                case RenderTreeEditType.SetAttribute:
                {
                    var node = WebViewRenderer.DOMBuilder.Child(CurrentNode, edit.SiblingIndex);
                    if (frame.AttributeValue is EventCallback callback)
                    {
                        WebViewRenderer.DOMBuilder.SetEvent(node, frame.Sequence, frame.AttributeName, callback, frame.AttributeEventUpdatesAttributeName);
                    }
                    else
                    {
                        WebViewRenderer.DOMBuilder.SetAttribute(node, frame.Sequence, frame.AttributeName, frame.AttributeValue);
                    }
                    //WebViewRenderer.DOMManager.SetAttribute(CurrentNode, frame.Sequence, frame.AttributeName, frame.AttributeValue);
                }
                break;

                case RenderTreeEditType.RemoveAttribute:
                {
                    WebViewRenderer.DOMBuilder.RemoveAttribute(CurrentNode, frame.Sequence, frame.AttributeName);
                }
                break;

                case RenderTreeEditType.StepIn:
                    CurrentNode = WebViewRenderer.DOMBuilder.Child(CurrentNode, edit.SiblingIndex);
                    break;

                case RenderTreeEditType.StepOut:
                    CurrentNode = WebViewRenderer.DOMBuilder.Parent(CurrentNode);
                    break;

                case RenderTreeEditType.PermutationListEntry:
                case RenderTreeEditType.PermutationListEnd:
                default:
                    throw new NotImplementedException($"Invalid edit type: {edit.Type}");
                }
            }
        }