public MirrorUtility(Mirror.FileNameFilter fileNameFilter = null)
        {
            Mirror = new Mirror(Watcher, new SequentialId(), fileNameFilter)
            {
                IdleDelay = TimeSpan.FromMilliseconds(value: 10)
            };

            Mirror.EntryFound       += entryFound;
            Mirror.ProcessingChange += processingChange;

            Mirror.EnqueuedCreatedEntry += enqueuedCreatedEntry;
            Mirror.EnqueuedDeletedEntry += enqueuedDeletedEntry;
            Mirror.EnqueuedMovedEntry   += enqueuedMovedEntry;

            Mirror.ProcessingCreatedEntry += processingCreatedEntry;
            Mirror.ProcessingDeletedEntry += processingDeletedEntry;
            Mirror.ProcessingMovedEntry   += processingMovedEntry;

            Mirror.Idle                 += mirrorIdle;
            Mirror.EntryAccessError     += entryAccessError;
            Mirror.BackgroundLoopFailed += backgroundLoopFailed;

            Mirror.FileCreated += fileCreatedNotification;
            Mirror.FileDeleted += fileDeletedNotification;
            Mirror.FileMoved   += fileMovedNotification;

            Mirror.DirectoryScanStarted     += directoryScanStarted;
            Mirror.DirectoryScanFinished    += directoryScanFinished;
            Mirror.DirectoryScanInterrupted += directoryScanInterrupted;
            Mirror.DirectoryScanNotFound    += directoryScanNotFound;
        }
        /// <summary>
        /// Maintains an up-to-date index of content of specified files and directories
        /// </summary>
        /// <param name="fileNameFilter">A filtering callback to determine wich files need to be indexed.
        ///   By default all files are indexed.</param>
        /// <param name="additionalWordChars">Additional non-word-separator characters for <see cref="ILexer"/></param>
        /// <param name="maxWordLength">Maximum word length to be returned by <see cref="ILexer"/></param>
        /// <param name="caseSensitive">Whether index search is case sensitive</param>
        /// <param name="indexDirectory">A directory to store index files</param>
        /// <param name="maxFileLength">Maximum length of indexed file</param>
        /// <param name="maxReadAttempts">Maximum read attempts when file system denies access to the file</param>
        /// <param name="lexerFactory">Creates instances of <see cref="ILexer"/> to parse text into a
        /// sequence of <see cref="IToken"/></param>
        /// <param name="encodingDetector">Provides encoding detection functionality. By default
        ///   <see cref="Encoding.UTF8"/>is assumed.</param>
        public static IndexFacade Create(
            Mirror.FileNameFilter fileNameFilter   = null,
            IEnumerable <char> additionalWordChars = null,
            int?maxWordLength          = null,
            bool?caseSensitive         = null,
            string indexDirectory      = null,
            long?maxFileLength         = null,
            int?maxReadAttempts        = null,
            ILexerFactory lexerFactory = null,
            Func <FileInfo, Encoding> encodingDetector = null)
        {
            if (additionalWordChars != null && lexerFactory != null)
            {
                throw new ArgumentException($"setting both {nameof(additionalWordChars)} and {nameof(lexerFactory)} is not supported");
            }

            if (maxWordLength.HasValue && lexerFactory != null)
            {
                throw new ArgumentException($"setting both {nameof(maxWordLength)} and {nameof(lexerFactory)} is not supported");
            }

            if (caseSensitive.HasValue && lexerFactory != null)
            {
                throw new ArgumentException($"setting both {nameof(caseSensitive)} and {nameof(lexerFactory)} is not supported");
            }

            DefaultLexerFactory defaultLexerFactory = null;

            if (additionalWordChars != null || maxWordLength.HasValue || caseSensitive.HasValue)
            {
                defaultLexerFactory = new DefaultLexerFactory();
                lexerFactory        = defaultLexerFactory;
            }

            if (additionalWordChars != null)
            {
                defaultLexerFactory.AdditionalWordChars.UnionWith(additionalWordChars);
            }

            if (maxWordLength.HasValue)
            {
                defaultLexerFactory.MaxWordLength = maxWordLength.Value;
            }

            if (caseSensitive.HasValue)
            {
                defaultLexerFactory.IsPreservingCase = caseSensitive.Value;
            }

            var indexEngine   = new LuceneIndexEngine(indexDirectory, lexerFactory);
            var watcher       = new Watcher();
            var mirror        = new Mirror(watcher, new SequentialId(), fileNameFilter);
            var taskProcessor = new IndexingTaskProcessor(indexEngine, encodingDetector);

            if (maxFileLength.HasValue)
            {
                taskProcessor.MaxFileLength = maxFileLength.Value;
            }

            if (maxReadAttempts.HasValue)
            {
                taskProcessor.MaxReadAttempts = maxReadAttempts.Value;
            }

            return(new IndexFacade(watcher, mirror, taskProcessor, indexEngine));
        }