using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
using CBR.Core.Files;
using CBR.Core.Helpers;
using CBR.Core.Models;
using SevenZip;
namespace CBR.Core.Services
{
public class CatalogService
{
#region ----------------SINGLETON----------------
public static readonly CatalogService Instance = new CatalogService();
/// <summary>
/// Private constructor for singleton pattern
/// </summary>
private CatalogService()
{
}
#endregion
#region ----------------PROPERTIES----------------
#endregion
#region -----------------LOAD-----------------
public Catalog Open(string path)
{
Catalog catlog = null;
try
{
//the file exist, try to load
if (File.Exists(path))
catlog = (Catalog)BinaryHelper.Deserialize(path);
//complete the load by loading the books
if (catlog != null)
{
catlog.CatalogFilePath = path;
Thread t = new Thread(new ParameterizedThreadStart(LaunchLoadBookThreads));
t.IsBackground = true;
t.Priority = ThreadPriority.Lowest;
t.Start(catlog);
WorkspaceService.Instance.AddRecent(catlog);
}
}
catch (Exception err)
{
ExceptionHelper.Manage("CatalogService:Load", err);
}
return catlog;
}
private static void LaunchLoadBookThreads(object param)
{
try
{
Catalog catlog = param as Catalog;
foreach (string filepath in catlog.BookInfoFilePath)
{
// load the book info + cover
Thread t = new Thread(new ParameterizedThreadStart(new BookInfoService().LoadBookInfo));
t.IsBackground = true;
t.Priority = ThreadPriority.Lowest;
t.Start(new ThreadExchangeData() { BookPath = filepath, ThreadCatalog = catlog });
}
}
catch (Exception err)
{
ExceptionHelper.Manage("CatalogService:LaunchLoadBookThreads", err);
}
}
#endregion
#region -----------------SAVE-----------------
public void SaveAs(Catalog catlog, string newFileName)
{
try
{
catlog.CatalogFilePath = newFileName;
Save(catlog);
}
catch (Exception err)
{
ExceptionHelper.Manage("CatalogService:SaveAs", err);
}
}
public void Save(Catalog catlog)
{
try
{
if (IsDirty(catlog))
{
//remove the book without covers
//RemoveDirtyBooks(CurrentCatalog);
//save catalog file info
BinaryHelper.Serialize(catlog.CatalogFilePath, catlog);
//complete the save by saving the books
if (catlog.BookInfoFilePath.Count > 0)
{
foreach (Book bk in catlog.Books.Where(bkk => bkk.IsDirty))
{
Thread t = new Thread(new ParameterizedThreadStart(new BookInfoService().SaveBookInfo));
t.IsBackground = true;
t.Priority = ThreadPriority.BelowNormal;
t.Start(bk);
}
}
}
}
catch (Exception err)
{
ExceptionHelper.Manage("CatalogService:SaveCatalog", err);
}
}
#endregion
#region -----------------DIRECTORY PARSING-----------------
internal void ParseDirectoryRecursive(object param)
{
ThreadExchangeData ted = param as ThreadExchangeData;
try
{
DirectoryInfo directory = new DirectoryInfo((string)ted.BookPath);
if (!directory.Exists)
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate
{
MessageBox.Show("Catalog path does not exist! Please check the options box");
});
return;
}
foreach (FileInfo file in directory.GetFiles("*.*"))
{
if (FileService.Instance.FindBookFilterByExt(file.Extension) != null)
{
if (!BookExistInCollection(ted.ThreadCatalog, file.FullName))
{
Book bkk = BookServiceFactory.Instance.GetService(file.FullName).CreateBookWithCover(BookFolder, file);
Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate
{
ted.ThreadCatalog.Books.Add(bkk);
});
ted.ThreadCatalog.BookInfoFilePath.Add(bkk.BookInfoFilePath);
ted.ThreadCatalog.IsDirty = true;
}
}
}
foreach (DirectoryInfo dir in directory.GetDirectories("*", SearchOption.TopDirectoryOnly))
{
ted.BookPath = dir.FullName;
ParseDirectoryRecursive(ted);
}
}
catch (Exception err)
{
ExceptionHelper.Manage("CatalogService:ParseDirectoryRecursive", err);
}
}
internal bool BookExistInCollection(Catalog catlog, string filepath)
{
return catlog.Books.AsParallel().Count(p => p.FilePath == filepath) == 0 ? false : true;
}
#endregion
#region -----------------REFRESH-----------------
public void Refresh(Catalog catlog)
{
try
{
Thread t = new Thread(new ParameterizedThreadStart(RefreshThread));
t.IsBackground = true;
t.Priority = ThreadPriority.BelowNormal;
t.Start(new ThreadExchangeData() { BookPath = catlog.BookFolder, ThreadCatalog = catlog });
}
catch (Exception err)
{
ExceptionHelper.Manage("CatalogService:Refresh", err);
}
}
internal void RefreshThread(object param)
{
ThreadExchangeData ted = param as ThreadExchangeData;
try
{
//first, remove unfounded books
List<Book> temp = new List<Book>();
foreach (Book bk in ted.ThreadCatalog.Books)
{
if (!File.Exists(bk.FilePath))
temp.Add(bk);
}
foreach (Book bk in temp)
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate
{
ted.ThreadCatalog.BookInfoFilePath.Remove(bk.BookInfoFilePath);
ted.ThreadCatalog.Books.Remove(bk);
ted.ThreadCatalog.IsDirty = true;
});
ted.ThreadCatalog.IsDirty = true;
}
//then add the new ones
ParseDirectoryRecursive(ted);
}
catch (Exception err)
{
ExceptionHelper.Manage("CatalogService:RefreshThread", err);
}
}
#endregion
#region -----------------BOOKS-----------------
private string _bookFolfer = string.Empty;
internal string BookFolder
{
get
{
if( string.IsNullOrEmpty(_bookFolfer) )
{
_bookFolfer = Path.Combine(DirectoryHelper.ApplicationPath, "BookInfos");
DirectoryHelper.Check(_bookFolfer);
}
return _bookFolfer;
}
}
public void AddBook(Catalog catlog, string bookFile)
{
ThreadExchangeData ted = new ThreadExchangeData();
try
{
FileInfo fi = new FileInfo(bookFile);
if (FileService.Instance.FindBookFilterByExt(fi.Extension) != null)
{
if (!BookExistInCollection(catlog, fi.FullName))
{
Book bkk = BookServiceFactory.Instance.GetService(fi.FullName).CreateBookWithCover(BookFolder, fi);
catlog.Books.Add(bkk);
catlog.BookInfoFilePath.Add(bkk.BookInfoFilePath);
catlog.IsDirty = true;
}
}
}
catch (Exception err)
{
ExceptionHelper.Manage("CatalogService:AddBook", err);
}
}
//internal void AddBook(ThreadExchangeData ted, FileInfo file)
//{
// string bookDir = Path.Combine(ApplicationPath, "BookInfos");
// if (!Directory.Exists(bookDir))
// Directory.CreateDirectory(bookDir);
// Book bk = new Book(GetBookInfoName(file), file.FullName, true);
// bk.Size = file.Length;
// ted.ThreadCatalog.Books.Add(bk);
// ted.ThreadCatalog.BookInfoFilePath.Add(bk.BookInfoFilePath);
// ted.ThreadCatalog.IsDirty = true;
//}
//internal string GetBookInfoName(FileInfo file)
//{
// string bookDir = Path.Combine(ApplicationPath, "BookInfos");
// return Path.Combine(bookDir, file.DirectoryName.Replace(file.Directory.Root.Name, "").Replace('\\', '.') + "." + file.Name + ".cbb");
//}
public void Fill(Catalog cat, string bookPath)
{
ThreadExchangeData ted = new ThreadExchangeData();
try
{
cat.BookFolder = bookPath;
ted.ThreadCatalog = cat;
ted.BookPath = cat.BookFolder;
Thread t = new Thread(new ParameterizedThreadStart(ParseDirectoryRecursive));
t.IsBackground = true;
t.Priority = ThreadPriority.BelowNormal;
t.Start(ted);
}
catch (Exception err)
{
ExceptionHelper.Manage("CatalogService:Create", err);
}
}
public bool IsDirty(Catalog catlog)
{
try
{
return (catlog.IsDirty || catlog.Books.AsParallel().Count(p => p.IsDirty == true) != 0 );
}
catch (Exception err)
{
ExceptionHelper.Manage("CatalogService:IsDirty", err);
}
return false;
}
public bool IsDynamic(Catalog catlog)
{
try
{
return (catlog.Books.AsParallel().Count(b => b.Pages.AsParallel().Count( p => p.Frames.Count !=0 ) != 0) != 0);
}
catch (Exception err)
{
ExceptionHelper.Manage("CatalogService:IsDynamic", err);
}
return false;
}
#endregion
}
}