/// <summary>Show the lookup UI for the current target.</summary>
        private void ShowLookup()
        {
            GameHelper.InterceptErrors("looking that up", () =>
            {
                using (ICumulativeLog log = this.GetTaskLog())
                {
                    log.Append("Lookup Anything received a lookup request. ");

                    // validate version
                    string versionError = GameHelper.ValidateGameVersion();
                    if (versionError != null)
                    {
                        GameHelper.ShowErrorMessage(versionError);
                        Log.Error(versionError);
                        return;
                    }

                    // get target
                    ISubject subject = null;
                    if (Game1.activeClickableMenu != null)
                    {
                        log.Append($"Searching the open '{Game1.activeClickableMenu.GetType().Name}' menu... ");
                        subject = this.TargetFactory.GetSubjectFrom(Game1.activeClickableMenu, GameHelper.GetScreenCoordinatesFromCursor());
                    }
                    else
                    {
                        log.Append("Searching the world... ");
                        subject = this.TargetFactory.GetSubjectFrom(Game1.currentLocation, Game1.currentCursorTile, GameHelper.GetScreenCoordinatesFromCursor());
                    }
                    if (subject == null)
                    {
                        log.AppendLine("no target found.");
                        return;
                    }


                    // show lookup UI
                    log.AppendLine($"showing {subject.GetType().Name}::{subject.Type}::{subject.Name}.");
                    this.PreviousMenu         = Game1.activeClickableMenu;
                    Game1.activeClickableMenu = new LookupMenu(subject, this.Metadata);
                }
            });
        }
        /*********
        ** Public methods
        *********/
        /// <summary>Initialise the mod.</summary>
        public override void Entry(params object[] objects)
        {
            using (ICumulativeLog log = new CumulativeLog())
            {
                log.AppendLine("Lookup Anything initialising...");

                // validate version
                log.Append("checking game/API version... ");
                string versionError = GameHelper.ValidateGameVersion();
                if (versionError != null)
                {
                    Log.Error(versionError);
                }
                log.AppendLine("OK!");

                // load config
                log.Append("loading config... ");
                this.Config = new RawModConfig().InitializeConfig(this.BaseConfigPath).GetParsed();
                log.AppendLine(this.Config.DebugLog ? $"loaded: {JsonConvert.SerializeObject(this.Config)}" : "OK!");

                // load database
                log.Append("loading database... ");
                this.LoadMetadata();
#if TEST_BUILD
                this.OverrideFileWatcher = new FileSystemWatcher(this.PathOnDisk, this.DatabaseFileName)
                {
                    EnableRaisingEvents = true
                };
                this.OverrideFileWatcher.Changed += (sender, e) =>
                {
                    this.LoadMetadata();
                    this.TargetFactory  = new TargetFactory(this.Metadata);
                    this.DebugInterface = new DebugInterface(this.TargetFactory, this.Config)
                    {
                        Enabled = this.DebugInterface.Enabled
                    };
                };
#endif
                log.AppendLine("OK!");

                // initialise functionality
                log.Append("initialising framework... ");
                this.CurrentVersion = UpdateHelper.GetSemanticVersion(this.Manifest.Version);
                this.TargetFactory  = new TargetFactory(this.Metadata);
                this.DebugInterface = new DebugInterface(this.TargetFactory, this.Config);
                log.AppendLine("OK!");

                // hook up events
                log.Append("registering event listeners... ");
                {
                    // reset low-level cache once per game day (used for expensive queries that don't change within a day)
                    PlayerEvents.LoadedGame += (sender, e) => GameHelper.ResetCache(this.Metadata);
                    TimeEvents.OnNewDay     += (sender, e) => GameHelper.ResetCache(this.Metadata);

                    // hook up game events
                    GameEvents.GameLoaded += (sender, e) => this.ReceiveGameLoaded();
                    GraphicsEvents.OnPostRenderHudEvent += (sender, e) => this.ReceiveInterfaceRendering(Game1.spriteBatch);
                    MenuEvents.MenuClosed += (sender, e) => this.ReceiveMenuClosed(e.PriorMenu);
                    if (this.Config.SuppressGameDebug)
                    {
                        GameEvents.HalfSecondTick += (sender, e) => this.SuppressGameDebug();
                    }

                    // hook up keyboard
                    if (this.Config.Keyboard.HasAny())
                    {
                        ControlEvents.KeyPressed += (sender, e) => this.ReceiveKeyPress(e.KeyPressed, this.Config.Keyboard);
                        if (this.Config.HideOnKeyUp)
                        {
                            ControlEvents.KeyReleased += (sender, e) => this.ReceiveKeyRelease(e.KeyPressed, this.Config.Keyboard);
                        }
                    }

                    // hook up controller
                    if (this.Config.Controller.HasAny())
                    {
                        ControlEvents.ControllerButtonPressed  += (sender, e) => this.ReceiveKeyPress(e.ButtonPressed, this.Config.Controller);
                        ControlEvents.ControllerTriggerPressed += (sender, e) => this.ReceiveKeyPress(e.ButtonPressed, this.Config.Controller);
                        if (this.Config.HideOnKeyUp)
                        {
                            ControlEvents.ControllerButtonReleased  += (sender, e) => this.ReceiveKeyRelease(e.ButtonReleased, this.Config.Controller);
                            ControlEvents.ControllerTriggerReleased += (sender, e) => this.ReceiveKeyRelease(e.ButtonReleased, this.Config.Controller);
                        }
                    }
                }
                log.AppendLine("OK!");

                log.AppendLine(this.Config.DebugLog ? "ready!" : "ready! further logging disabled by config.");
            }
        }