/// <summary>
        /// Handles the Click event of the lbSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void lbSave_Click(object sender, EventArgs e)
        {
            var rockContext   = new RockContext();
            var layoutService = new LayoutService(rockContext);

            var layout = layoutService.Get(PageParameter("LayoutId").AsInteger());

            if (layout == null)
            {
                layout = new Layout
                {
                    SiteId = PageParameter("SiteId").AsInteger()
                };
                layoutService.Add(layout);
            }

            layout.Name               = tbName.Text;
            layout.FileName           = tbName.Text + ".xaml";
            layout.Description        = tbDescription.Text;
            layout.LayoutMobilePhone  = cePhoneLayout.Text;
            layout.LayoutMobileTablet = ceTabletLayout.Text;

            rockContext.SaveChanges();

            NavigateToParentPage(new Dictionary <string, string>
            {
                { "SiteId", PageParameter("SiteId") },
                { "Tab", "Layouts" }
            });
        }
        /// <summary>
        /// Handles the Click event of the btnSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        protected void btnSave_Click(object sender, EventArgs e)
        {
            if (Page.IsValid)
            {
                LayoutService layoutService = new LayoutService();
                Layout        layout;

                int layoutId = int.Parse(hfLayoutId.Value);

                // if adding a new layout
                if (layoutId.Equals(0))
                {
                    layout = new Layout {
                        Id = 0
                    };
                    layout.SiteId = hfSiteId.ValueAsInt();
                }
                else
                {
                    //load existing group member
                    layout = layoutService.Get(layoutId);
                }

                layout.Name        = tbLayoutName.Text;
                layout.Description = tbDescription.Text;
                layout.FileName    = ddlLayout.SelectedValue;

                if (!layout.IsValid)
                {
                    return;
                }

                RockTransactionScope.WrapTransaction(() =>
                {
                    if (layout.Id.Equals(0))
                    {
                        layoutService.Add(layout, CurrentPersonId);
                    }

                    layoutService.Save(layout, CurrentPersonId);
                });

                LayoutCache.Flush(layout.Id);

                Dictionary <string, string> qryString = new Dictionary <string, string>();
                qryString["siteId"] = hfSiteId.Value;
                NavigateToParentPage(qryString);
            }
        }
        /// <summary>
        /// Handles the Click event of the btnSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        protected void btnSave_Click(object sender, EventArgs e)
        {
            if (Page.IsValid)
            {
                var           rockContext   = new RockContext();
                LayoutService layoutService = new LayoutService(rockContext);
                Layout        layout;

                int layoutId = int.Parse(hfLayoutId.Value);

                // if adding a new layout
                if (layoutId.Equals(0))
                {
                    layout = new Layout {
                        Id = 0
                    };
                    layout.SiteId = hfSiteId.ValueAsInt();
                }
                else
                {
                    //load existing group member
                    layout = layoutService.Get(layoutId);
                }

                layout.Name        = tbLayoutName.Text;
                layout.Description = tbDescription.Text;
                layout.FileName    = ddlLayout.SelectedValue;

                if (!layout.IsValid)
                {
                    return;
                }

                if (layout.Id.Equals(0))
                {
                    layoutService.Add(layout);
                }

                rockContext.SaveChanges();

                LayoutCache.Flush(layout.Id);

                Dictionary <string, string> qryParams = new Dictionary <string, string>();
                qryParams["layoutId"] = layout.Id.ToString();
                NavigateToPage(RockPage.Guid, qryParams);
            }
        }
        /// <summary>
        /// Recursively saves Pages and associated Blocks, PageRoutes and PageContexts.
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="page">The current Page to save</param>
        /// <param name="newBlockTypes">List of BlockTypes not currently installed</param>
        /// <param name="parentPageId">Id of the current Page's parent</param>
        /// <param name="siteId">Id of the site the current Page is being imported into</param>
        private void SavePages(RockContext rockContext, Page page, IEnumerable <BlockType> newBlockTypes, int parentPageId, int siteId)
        {
            rockContext = rockContext ?? new RockContext();

            // find layout
            var    layoutService = new LayoutService(rockContext);
            Layout layout        = new Layout();

            if (page.Layout != null)
            {
                layout = layoutService.GetBySiteId(siteId).Where(l => l.Name == page.Layout.Name && l.FileName == page.Layout.FileName).FirstOrDefault();
                if (layout == null)
                {
                    layout          = new Layout();
                    layout.FileName = page.Layout.FileName;
                    layout.Name     = page.Layout.Name;
                    layout.SiteId   = siteId;
                    layoutService.Add(layout);
                    rockContext.SaveChanges();
                }
            }
            else
            {
                layout = layoutService.GetBySiteId(siteId).Where(l => l.Name.Contains("Full") || l.Name.Contains("Home")).First();
            }
            int layoutId = layout.Id;

            // Force shallow copies on entities so save operations are more atomic and don't get hosed
            // by nested object references.
            var pg         = page.Clone(deepCopy: false);
            var blockTypes = newBlockTypes.ToList();

            pg.ParentPageId = parentPageId;
            pg.LayoutId     = layoutId;

            var pageService = new PageService(rockContext);

            pageService.Add(pg);
            rockContext.SaveChanges();

            var blockService = new BlockService(rockContext);

            foreach (var block in page.Blocks ?? new List <Block>())
            {
                var blockType = blockTypes.FirstOrDefault(bt => block.BlockType.Path == bt.Path);
                var b         = block.Clone(deepCopy: false);
                b.PageId = pg.Id;

                if (blockType != null)
                {
                    b.BlockTypeId = blockType.Id;
                }

                blockService.Add(b);
            }
            rockContext.SaveChanges();

            var pageRouteService = new PageRouteService(rockContext);

            foreach (var pageRoute in page.PageRoutes ?? new List <PageRoute>())
            {
                var pr = pageRoute.Clone(deepCopy: false);
                pr.PageId = pg.Id;
                pageRouteService.Add(pr);
            }
            rockContext.SaveChanges();

            var pageContextService = new PageContextService(rockContext);

            foreach (var pageContext in page.PageContexts ?? new List <PageContext>())
            {
                var pc = pageContext.Clone(deepCopy: false);
                pc.PageId = pg.Id;
                pageContextService.Add(pc);
            }
            rockContext.SaveChanges();

            foreach (var p in page.Pages ?? new List <Page>())
            {
                SavePages(rockContext, p, blockTypes, pg.Id, siteId);
            }
        }
        /// <summary>
        /// Handles the Click event of the btnSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void btnSave_Click(object sender, EventArgs e)
        {
            var applicationId = PageParameter(PageParameterKey.SiteId).AsInteger();

            var rockContext = new RockContext();
            var siteService = new SiteService(rockContext);
            var site        = siteService.Get(applicationId);

            var additionalSettings = new AppleTvApplicationSettings();
            var isNewSite          = false;

            // Site is new so create one
            if (site == null)
            {
                site = new Site();
                siteService.Add(site);
                isNewSite = true;
            }
            else
            {
                additionalSettings = JsonConvert.DeserializeObject <AppleTvApplicationSettings>(site.AdditionalSettings);
            }

            site.Name        = tbApplicationName.Text;
            site.Description = tbDescription.Text;
            site.IsActive    = cbIsActive.Checked;
            site.SiteType    = SiteType.Tv;

            additionalSettings.ApplicationScript = ceApplicationJavaScript.Text;
            additionalSettings.ApplicationStyles = ceApplicationStyles.Text;
            additionalSettings.TvApplicationType = TvApplicationType.AppleTv;

            // Login page
            site.LoginPageId      = ppLoginPage.PageId;
            site.LoginPageRouteId = ppLoginPage.PageRouteId;

            // Create/Modify API Key
            additionalSettings.ApiKeyId = SaveApiKey(additionalSettings.ApiKeyId, txtApiKey.Text, string.Format("tv_application_{0}", site.Id), rockContext);
            site.AdditionalSettings     = additionalSettings.ToJson();

            rockContext.SaveChanges();

            // Create interaction channel for this site
            var interactionChannelService   = new InteractionChannelService(rockContext);
            int channelMediumWebsiteValueId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.INTERACTIONCHANNELTYPE_WEBSITE.AsGuid()).Id;
            var interactionChannelForSite   = interactionChannelService.Queryable()
                                              .Where(a => a.ChannelTypeMediumValueId == channelMediumWebsiteValueId && a.ChannelEntityId == site.Id).FirstOrDefault();

            if (interactionChannelForSite == null)
            {
                interactionChannelForSite = new InteractionChannel();
                interactionChannelForSite.ChannelTypeMediumValueId = channelMediumWebsiteValueId;
                interactionChannelForSite.ChannelEntityId          = site.Id;
                interactionChannelService.Add(interactionChannelForSite);
            }

            interactionChannelForSite.Name = site.Name;
            interactionChannelForSite.RetentionDuration     = nbPageViewRetentionPeriodDays.Text.AsIntegerOrNull();
            interactionChannelForSite.ComponentEntityTypeId = EntityTypeCache.Get <Rock.Model.Page>().Id;

            rockContext.SaveChanges();

            // If this is a new site then we also need to add a layout record and a 'default page'
            if (isNewSite)
            {
                var layoutService = new LayoutService(rockContext);

                var layout = new Layout
                {
                    Name        = "Homepage",
                    FileName    = "Homepage.xaml",
                    Description = string.Empty,
                    SiteId      = site.Id
                };

                layoutService.Add(layout);
                rockContext.SaveChanges();

                var pageService = new PageService(rockContext);
                var page        = new Rock.Model.Page {
                    InternalName     = "Start Screen",
                    BrowserTitle     = "Start Screen",
                    PageTitle        = "Start Screen",
                    DisplayInNavWhen = DisplayInNavWhen.WhenAllowed,
                    Description      = string.Empty,
                    LayoutId         = layout.Id,
                    Order            = 0
                };

                pageService.Add(page);
                rockContext.SaveChanges();

                site.DefaultPageId = page.Id;
                rockContext.SaveChanges();
            }

            // If the save was successful, reload the page using the new record Id.
            var qryParams = new Dictionary <string, string>();

            qryParams[PageParameterKey.SiteId] = site.Id.ToString();

            NavigateToPage(RockPage.Guid, qryParams);
        }