private Widget ParseWidget(Sitemap aSitemap, XElement aRoot)
        {
            var type = aRoot.Element("type").Value;
            var label = aRoot.Element("label").Value;
            var icon = aRoot.Element("icon").Value;

            var widget = new Widget(type, label, icon);

            if (widget.Type == Widget.WidgetType.Image)
                widget.Url = new Uri(new UriBuilder(aSitemap.Link.Scheme, aSitemap.Link.Host, aSitemap.Link.Port).Uri, aRoot.Element("url").Value);

            if (widget.Type == Widget.WidgetType.Chart)
            {
                widget.Period = aRoot.Element("period").Value;
                widget.Refresh = int.Parse(aRoot.Element("refresh").Value);
            }

            if (widget.Type == Widget.WidgetType.Setpoint)
            {
                widget.MinValue = double.Parse( aRoot.Element("minValue").Value,System.Globalization.NumberFormatInfo.InvariantInfo);
                widget.MaxValue = double.Parse( aRoot.Element("maxValue").Value,System.Globalization.NumberFormatInfo.InvariantInfo);
                widget.Step = double.Parse( aRoot.Element("step").Value,System.Globalization.NumberFormatInfo.InvariantInfo);
            }

            if (widget.Type == Widget.WidgetType.Video)
                widget.Url = new Uri(new UriBuilder(aSitemap.Link.Scheme, aSitemap.Link.Host, aSitemap.Link.Port).Uri, aRoot.Element("url").Value);

            if (widget.Type == Widget.WidgetType.Webview)
                widget.Url = new Uri(new UriBuilder(aSitemap.Link.Scheme, aSitemap.Link.Host, aSitemap.Link.Port).Uri, aRoot.Element("url").Value);

            if (widget.Type == Widget.WidgetType.Switch || widget.Type == Widget.WidgetType.Selection)
            {
                var mappings = aRoot.Elements("mapping");

                foreach(var mapping in mappings)
                {
                    var map_command = mapping.Element("command").Value;
                    var map_label = mapping.Element("label").Value;

                    widget.Mappings[map_label] = map_command;
                }
            }

            foreach (var child in aRoot.Elements("widget"))
            {
                widget.mWidgets.Add(ParseWidget(aSitemap, child));
            }

            var item = aRoot.Element("item");
            if (item != null)
            {
                widget.Item = ParseItem(aSitemap, item);
            }

            var linkedPage = aRoot.Element("linkedPage");
            if (linkedPage != null)
            {
                widget.LinkedPage = ParsePage(aSitemap, linkedPage);
            }
            return widget;
        }
        private bool UpdateWidget(Widget aOldWidget, Dictionary<string, object> aNewWidget)
        {
            var changed = false;

            var type = (Widget.WidgetType)Enum.Parse(typeof(Widget.WidgetType), (string)aNewWidget["type"], true);
            var label = (string)aNewWidget["label"];
            var icon = (string)aNewWidget["icon"];

            Dictionary<string, object> item = null;
            object obj = null;
            if (aNewWidget.TryGetValue("item", out obj))
                item = (Dictionary<string, object>)obj;

            List<Dictionary<string, object>> widgets = null;
            if (aNewWidget.TryGetValue("widget", out obj))
                widgets = obj as List<Dictionary<string, object>>;

            if (aOldWidget.Type != type)
            {
                changed = true;
                aOldWidget.Type = type;
            }

            aOldWidget.Label = label;
            aOldWidget.Icon = icon;

            if (aOldWidget.Item != null && item != null)
            {
                if (UpdateItem(aOldWidget.Item, item))
                    changed = true;
            }
            else if (aOldWidget.Item != null || item != null)
            {
                changed = true;

                if (aOldWidget.Item != null)
                {
                    aOldWidget.Item = null;
                }
                else
                {
                    // TODO: find/add item
                }
            }

            if (type == Widget.WidgetType.Video || type == Widget.WidgetType.Webview || type == Widget.WidgetType.Image)
            {
                var url = (string)aNewWidget["url"];
                aOldWidget.Url = new Uri(new UriBuilder(aOldWidget.Url.Scheme, aOldWidget.Url.Host, aOldWidget.Url.Port).Uri, url);
            }

            if (type == Widget.WidgetType.Chart)
            {
                aOldWidget.Period = (string)aNewWidget["period"];
                aOldWidget.Refresh = int.Parse((string)aNewWidget["refresh"]);
            }

            if (type == Widget.WidgetType.Setpoint)
            {
                aOldWidget.MinValue = double.Parse((string)aNewWidget["minValue"], System.Globalization.NumberFormatInfo.InvariantInfo);
                aOldWidget.MaxValue = double.Parse((string)aNewWidget["maxValue"], System.Globalization.NumberFormatInfo.InvariantInfo);
                aOldWidget.Step = double.Parse((string)aNewWidget["step"], System.Globalization.NumberFormatInfo.InvariantInfo);
            }

            if (widgets != null)
            {
                var idx = 0;
                for (idx = 0; idx < Math.Min(aOldWidget.mWidgets.Count, widgets.Count); ++idx)
                {
                    if (UpdateWidget(aOldWidget.mWidgets[idx], widgets[idx]))
                        changed = true;
                }

                if (idx < aOldWidget.mWidgets.Count)
                {
                    aOldWidget.mWidgets.RemoveRange(idx, aOldWidget.mWidgets.Count - idx);
                    changed = true;
                }

                if (idx < widgets.Count)
                {
                    // TODO: add additional widgets
                }
            }
            else if (aOldWidget.mWidgets.Count > 0)
            {
                // TODO: widgets removed?
            }

            aOldWidget.FireUpdated();

            return changed;   
        }
        private void UpdateWidget(Widget aWidget, XElement aRoot)
        {
            aWidget.Label = aRoot.Element("label").Value;
            aWidget.Icon = aRoot.Element("icon").Value;

            if (aWidget.Type == Widget.WidgetType.Image)
                aWidget.Url = new Uri(new UriBuilder(aWidget.Url.Scheme, aWidget.Url.Host, aWidget.Url.Port).Uri, aRoot.Element("url").Value);

            if (aWidget.Type == Widget.WidgetType.Chart)
            {
                aWidget.Period = aRoot.Element("period").Value;
                aWidget.Refresh = int.Parse(aRoot.Element("refresh").Value);
            }

            if (aWidget.Type == Widget.WidgetType.Setpoint)
            {
                aWidget.MinValue = double.Parse(aRoot.Element("minValue").Value, System.Globalization.NumberFormatInfo.InvariantInfo);
                aWidget.MaxValue = double.Parse(aRoot.Element("maxValue").Value, System.Globalization.NumberFormatInfo.InvariantInfo);
                aWidget.Step = double.Parse(aRoot.Element("step").Value, System.Globalization.NumberFormatInfo.InvariantInfo);
            }

            if (aWidget.Type == Widget.WidgetType.Video)
                aWidget.Url = new Uri(new UriBuilder(aWidget.Url.Scheme, aWidget.Url.Host, aWidget.Url.Port).Uri, aRoot.Element("url").Value);

            if (aWidget.Type == Widget.WidgetType.Webview)
                aWidget.Url = new Uri(new UriBuilder(aWidget.Url.Scheme, aWidget.Url.Host, aWidget.Url.Port).Uri, aRoot.Element("url").Value);

            var item = aRoot.Element("item");
            if (item != null)
            {
                UpdateItem(aWidget.Item, item);
            }

            var widgets = aRoot.Elements("widget").ToArray();

            for (var idx = 0; idx < widgets.Length; ++idx)
                UpdateWidget(aWidget.Widgets[idx], widgets[idx]);
        }