private void _changeSignLanguageLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            var collectionSettings = _model.Book.CollectionSettings;
            var l = CollectionSettingsDialog.ChangeLanguage(collectionSettings.SignLanguageIso639Code, CurrentSignLanguageName, false);

            if (l == null)
            {
                // no change; dialog cancelled
                return;
            }
            _changeSignLanguageLinkLabel.Text         = l.DesiredName;
            collectionSettings.SignLanguageIso639Code = l.LanguageTag;
            collectionSettings.SignLanguageName       = l.DesiredName;
            collectionSettings.Save();
        }
        public void RegisterWithApiHandler(BloomApiHandler apiHandler)
        {
            apiHandler.RegisterEndpointHandler(kApiUrlPart + "enterpriseEnabled", request =>
            {
                if (request.HttpMethod == HttpMethods.Get)
                {
                    lock (request)
                    {
                        request.ReplyWithBoolean(IsEnterpriseEnabled);
                    }
                }
                else                 // post
                {
                    System.Diagnostics.Debug.Fail("We shouldn't ever be using the 'post' version.");
                    request.PostSucceeded();
                }
            }, true);
            apiHandler.RegisterEnumEndpointHandler(kApiUrlPart + "enterpriseStatus",
                                                   request => _enterpriseStatus,
                                                   (request, status) =>
            {
                _enterpriseStatus = status;
                if (_enterpriseStatus == EnterpriseStatus.None)
                {
                    _knownBrandingInSubscriptionCode = true;
                    BrandingChangeHandler("Default", null);
                }
                else if (_enterpriseStatus == EnterpriseStatus.Community)
                {
                    BrandingChangeHandler("Local-Community", null);
                }
                else
                {
                    BrandingChangeHandler(GetBrandingFromCode(SubscriptionCode), SubscriptionCode);
                }
            }, false);
            apiHandler.RegisterEndpointHandler(kApiUrlPart + "legacyBrandingName",
                                               request => { request.ReplyWithText(LegacyBrandingName ?? ""); }, false);

            apiHandler.RegisterEndpointHandler(kApiUrlPart + "subscriptionCode", request =>
            {
                if (request.HttpMethod == HttpMethods.Get)
                {
                    request.ReplyWithText(SubscriptionCode ?? "");
                }
                else                 // post
                {
                    var requestData   = DynamicJson.Parse(request.RequiredPostJson());
                    SubscriptionCode  = requestData.subscriptionCode;
                    _enterpriseExpiry = GetExpirationDate(SubscriptionCode);
                    if (_enterpriseExpiry < DateTime.Now)                     // expired or invalid
                    {
                        BrandingChangeHandler("Default", null);
                    }
                    else
                    {
                        _knownBrandingInSubscriptionCode = BrandingChangeHandler(GetBrandingFromCode(SubscriptionCode), SubscriptionCode);
                        if (!_knownBrandingInSubscriptionCode)
                        {
                            BrandingChangeHandler("Default", null);                             // Review: or just leave unchanged?
                        }
                    }
                    request.PostSucceeded();
                }
            }, false);
            apiHandler.RegisterEndpointHandler(kApiUrlPart + "enterpriseSummary", request =>
            {
                string branding = "";
                if (_enterpriseStatus == EnterpriseStatus.Community)
                {
                    branding = "Local-Community";
                }
                else if (_enterpriseStatus == EnterpriseStatus.Subscription)
                {
                    branding = _enterpriseExpiry == DateTime.MinValue ? "" : GetBrandingFromCode(SubscriptionCode);
                }
                var html = GetSummaryHtml(branding);
                request.ReplyWithText(html);
            }, false);
            apiHandler.RegisterEndpointHandler(kApiUrlPart + "enterpriseExpiry", request =>
            {
                if (_enterpriseExpiry == DateTime.MinValue)
                {
                    if (SubscriptionCodeLooksIncomplete(SubscriptionCode))
                    {
                        request.ReplyWithText("incomplete");
                    }
                    else
                    {
                        request.ReplyWithText("null");
                    }
                }
                else if (_knownBrandingInSubscriptionCode)
                {
                    // O is ISO 8601, the only format I can find that C# ToString() can produce and JS is guaranteed to parse.
                    // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse
                    request.ReplyWithText(_enterpriseExpiry.ToString("O", CultureInfo.InvariantCulture));
                }
                else
                {
                    request.ReplyWithText("unknown");
                }
            }, false);
            apiHandler.RegisterEndpointHandler(kApiUrlPart + "hasSubscriptionFiles", request =>
            {
                var haveFiles = BrandingProject.HaveFilesForBranding(GetBrandingFromCode(SubscriptionCode));
                if (haveFiles)
                {
                    request.ReplyWithText("true");
                }
                else
                {
                    request.ReplyWithText("false");
                }
            }, false);

            // Enhance: The get here has one signature {brandingProjectName, defaultBookshelf} while the post has another (defaultBookshelfId:string).
            // It's
            apiHandler.RegisterEndpointHandler(kApiUrlPart + "bookShelfData", request =>
            {
                if (request.HttpMethod == HttpMethods.Get)
                {
                    var brandingProjectName    = _collectionSettings.BrandingProjectKey;
                    var defaultBookshelfUrlKey = _collectionSettings.DefaultBookshelf;
                    request.ReplyWithJson(new { brandingProjectName, defaultBookshelfUrlKey });
                }
                else
                {
                    // post: doesn't include the brandingProjectName, as this is not where we edit that.
                    var newShelf = request.RequiredPostString();
                    if (newShelf == "none")
                    {
                        newShelf = "";                         // RequiredPostString won't allow us to just pass this
                    }
                    if (DialogBeingEdited != null)
                    {
                        DialogBeingEdited.PendingDefaultBookshelf = newShelf;
                    }
                    request.PostSucceeded();
                }
            }, false);
            // Calls to handle communication with new FontScriptControl on Book Making tab
            apiHandler.RegisterEndpointHandler(kApiUrlPart + "specialScriptSettings", request =>
            {
                if (request.HttpMethod == HttpMethods.Get)
                {
                    return;                     // Should be a post
                }
                // Should contain a languageName and a (1-based) language number.
                var data           = DynamicJson.Parse(request.RequiredPostJson());
                var languageNumber = (int)data.languageNumber;
                var languageName   = (string)data.languageName;
                var needRestart    = CollectionSettingsDialog.FontSettingsLinkClicked(_collectionSettings, languageName, languageNumber);
                if (DialogBeingEdited != null && needRestart)
                {
                    DialogBeingEdited.ChangeThatRequiresRestart();
                }
                request.PostSucceeded();
            }, true);
            apiHandler.RegisterEndpointHandler(kApiUrlPart + "setFontForLanguage", request =>
            {
                if (request.HttpMethod == HttpMethods.Get)
                {
                    return;                     // Should be a post
                }
                // Should contain a 1-based language number and a font name
                var data           = DynamicJson.Parse(request.RequiredPostJson());
                var languageNumber = (int)data.languageNumber;
                var fontName       = (string)data.fontName;
                UpdatePendingFontName(fontName, languageNumber);
                request.PostSucceeded();
            }, true);
            apiHandler.RegisterEndpointHandler(kApiUrlPart + "currentFontData", request =>
            {
                if (request.HttpMethod == HttpMethods.Post)
                {
                    return;                     // Should be a get
                }
                // We want to return the data (languageName/fontName) for each active collection language
                request.ReplyWithJson(GetLanguageData());
            }, true);
            apiHandler.RegisterEndpointHandler(kApiUrlPart + "numberingStyle", request =>
            {
                if (request.HttpMethod == HttpMethods.Get)
                {
                    // Should return all available numbering styles and the current style
                    request.ReplyWithJson(GetNumberingStyleData());
                }
                else
                {
                    // We are receiving a pending numbering style change
                    var newNumberingStyle = request.RequiredPostString();
                    UpdatePendingNumberingStyle(newNumberingStyle);
                    request.PostSucceeded();
                }
            }, true);
            apiHandler.RegisterEndpointHandler(kApiUrlPart + "xmatter", request =>
            {
                if (request.HttpMethod == HttpMethods.Get)
                {
                    // Should return all available xMatters and the current selected xMatter
                    request.ReplyWithJson(SetupXMatterList());
                }
                else
                {
                    // We are receiving a pending xMatter change
                    var newXmatter = request.RequiredPostString();
                    UpdatePendingXmatter(newXmatter);
                    request.PostSucceeded();
                }
            }, true);
        }