public Book Add(Book model)
        {
            if (model == null)
            {
                BookLogger.Error($"{nameof(model)}is null");
                throw new ArgumentNullException(nameof(model));
            }

            if (this._listBooks.ToList().Contains(model))
            {
                BookLogger.Error($"Book with ISBN {model.ISBN} is alredy exists");
                throw new AddBookException(model.Name, model.ISBN);
            }

            using (var fs = new FileStream(this._fileStorage, FileMode.Append, FileAccess.Write, FileShare.Read))
            {
                using (BinaryWriter writer = new BinaryWriter(fs))
                {
                    SaveBook(writer, model);
                    BookLogger.Info($"Book with ISBN {model.ISBN} was added to storage");
                }
            }

            this._listBooks = this._listBooks.Concat(new[] { model });

            return(model);
        }
        public IEnumerable <Book> Load()
        {
            List <Book> bookList = new List <Book>();

            using (var fs = new FileStream(this._fileStorage, FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read))
            {
                using (BinaryReader reader = new BinaryReader(fs))
                {
                    while (reader.BaseStream.Position != reader.BaseStream.Length)
                    {
                        var readedBook = LoadData(reader);

                        if (readedBook == null)
                        {
                            BookLogger.Error($"{nameof(readedBook)} is null");
                            throw new ArgumentNullException(nameof(readedBook));
                        }

                        bookList.Add(readedBook);
                    }
                }
            }

            BookLogger.Info($"List books was loaded");
            return(bookList);
        }
        public Book Update(Book model)
        {
            if (model == null)
            {
                BookLogger.Error($"{nameof(model)} is null");
                throw new ArgumentNullException(nameof(model));
            }

            var deletedBook = Get(model.ISBN);

            if (deletedBook == null)
            {
                BookLogger.Error($"Book with ISBN {model.ISBN} doesn't exists in the storage");
                throw new DeleteBookException(model.Name, model.ISBN);
            }

            this._listBooks = this._listBooks.Except(new List <Book> {
                deletedBook
            });
            this._listBooks = this._listBooks.Concat(new[] { model });

            SaveBookList();
            BookLogger.Info($"Book with ISBN {model.ISBN} was updated");
            return(model);
        }
        /// <summary>
        /// Sorts book by tags name
        /// </summary>
        /// <param name="comparer">Tags name</param>
        /// <returns>Enumeration of books</returns>
        public IEnumerable <Book> SortBookByTag(IComparer <Book> comparer)
        {
            if (comparer == null)
            {
                BookLogger.Error($"{nameof(comparer)} is null value");
                throw new ArgumentNullException(nameof(comparer));
            }

            return(this._bookRepository.SortByTag(comparer));
        }
        /// <summary>
        /// Finds book by tags name and value
        /// </summary>
        /// <param name="filter">Filter</param>
        /// <returns>Enumeration of found books</returns>
        public IEnumerable <Book> FindBookByTag(Predicate <Book> filter)
        {
            if (filter == null)
            {
                BookLogger.Error($"{nameof(filter)} is null value");
                throw new ArgumentNullException(nameof(filter));
            }

            return(this._bookRepository.Find(filter));
        }
        /// <summary>
        /// Removes book
        /// </summary>
        /// <param name="book">Book</param>
        /// <returns><value>Book if it is removed</value>
        /// <value>null -otherwise</value></returns>
        public Book RemoveBook(Book book)
        {
            if (book == null)
            {
                BookLogger.Error($"{nameof(book)} is null value");
                throw new ArgumentNullException(nameof(book));
            }

            return(this._bookRepository.Delete(book));
        }
        public IEnumerable <Book> SortByTag(IComparer <Book> comparer)
        {
            if (comparer == null)
            {
                BookLogger.Error($"{nameof(comparer)} is null");
                throw new ArgumentNullException(nameof(comparer));
            }

            var sortedList = this._listBooks.ToList();

            sortedList.Sort(comparer);

            BookLogger.Info($"Books list was sorted");
            return(sortedList);
        }
        public Book Get(Book model)
        {
            var findElement = this.Find(x => x.ISBN == model.ISBN);

            if (!findElement.Any())
            {
                BookLogger.Warn($"{nameof(findElement)} with ISBN {model.ISBN} doesn't exists in the storage");
                return(null);
            }

            if (findElement.Count() > 1)
            {
                BookLogger.Error($"{nameof(findElement)} with ISBN {model.ISBN} shoud be one");
                throw new GetBookException(model.ISBN);
            }

            return(findElement.ToArray()[0]);
        }