/// <summary>
        /// Maintains an up-to-date index of content of specified files and directories
        /// </summary>
        public IndexFacade(
            Watcher watcher,
            Mirror mirror,
            IndexingTaskProcessor indexingTaskProcessor,
            IIndexEngine indexEngine)
        {
            _watcher = watcher;
            _mirror  = mirror;
            _indexingTaskProcessor = indexingTaskProcessor;
            _indexEngine           = indexEngine;

            _mirror.FileCreated += fileCreatead;
            _mirror.FileDeleted += fileDeleted;
            _mirror.FileMoved   += fileMoved;

            _mirror.EntryAccessError += fileAccessError;
            _indexingTaskProcessor.FileAccessError += fileAccessError;
        }
        /// <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));
        }