using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using CBR.Core.Helpers;
using System.IO;
using CBR.Core.Services;
namespace CBR.Core.Files.Conversion
{
public class BookFileConverter
{
#region ----------------------PROPERTIES----------------------
/// <summary>
/// The thread we are running in, but it can be null
/// </summary>
public BackgroundWorker Worker
{
get;
set;
}
/// <summary>
/// Thread event arg associated to the background worker, can be null
/// </summary>
public DoWorkEventArgs Event
{
get;
set;
}
/// <summary>
/// Thread result as PDFConvertParameters stored in the event
/// </summary>
public ContractParameters Settings
{
get
{
if (Event != null)
return (ContractParameters)Event.Result;
else
return null;
}
set
{
Event.Result = value;
}
}
#endregion
#region ----------------------CONSTRUCTORS----------------------
/// <summary>
/// Constructor
/// </summary>
/// <param name="worker"></param>
/// <param name="e"></param>
public BookFileConverter(BackgroundWorker worker, DoWorkEventArgs e)
{
Worker = worker;
Event = e;
Settings = (ContractParameters)e.Argument;
}
#endregion
#region ----------------------HELPERS----------------------
/// <summary>
/// Send progress mesage through the background worker
/// </summary>
/// <param name="message"></param>
private void Progress(string message)
{
if (Worker != null)
Worker.ReportProgress(0, message);
}
/// <summary>
/// Check if cancelling has been asked
/// </summary>
/// <returns></returns>
private bool CancelPending()
{
if (Worker == null)
return false;
if (Worker.CancellationPending)
{
Event.Cancel = true;
return true;
}
else return false;
}
#endregion
/// <summary>
/// convert pdf files regarding the parameters gived to the thread
/// </summary>
public void Convert()
{
try
{
Progress("Starting conversion...");
//get the contracts
IReaderContract reader = GetReader( Settings.InputType );
IWriterContract writer = GetWriter(Settings.OutputType);
//create the result file list
if (Settings.ResfreshLibrary)
Settings.ResultFiles = new List<string>();
// check output path
if (!string.IsNullOrEmpty(Settings.DestinationPath))
DirectoryHelper.Check(Settings.DestinationPath);
// just one file !
if ( !string.IsNullOrEmpty(Settings.InputFile) && File.Exists(Settings.InputFile) )
{
ConvertFile(reader, writer, Settings.InputFile, Path.GetDirectoryName(Settings.InputFile));
}
// folder input
if (!string.IsNullOrEmpty(Settings.InputPath) && Directory.Exists(Settings.InputPath))
{
if( Settings.InputType == BookType.ImageFile )
ConvertFolder(reader, writer, Settings.InputPath, Settings.InputPath);//image files
else
ConvertDirectoryRecursively(reader, writer, Settings.InputPath);// or folders
}
}
catch (Exception error)
{
ExceptionHelper.Manage("BookFileConverter:Convert", error);
Settings.Result = false;
}
finally
{
Progress("Conversion finished...");
}
}
#region ----------------------INTERNALS----------------------
internal IReaderContract GetReader(BookType typ)
{
if (typ == BookType.ImageFile) return new ImageFileReader();
if (typ == BookType.PDF) return new PDFImageReader();
if (typ == BookType.RARBased) return new RARImageReader();
if (typ == BookType.ZIPBased) return new RARImageReader();
if (typ == BookType.XPS) return new XPSImageReader();
throw new Exception("Reader not implemented");
}
internal IWriterContract GetWriter(BookType typ)
{
if (typ == BookType.ImageFile) return new ImageFileWriter();
if (typ == BookType.ZIPBased) return new ZIPWriter();
if (typ == BookType.XPS) return new XPSImageWriter();
throw new Exception("Writer not implemented");
}
/// <summary>
/// Convert a folder recursively regarding the settings
/// </summary>
/// <param name="inputFolder"></param>
private void ConvertDirectoryRecursively(IReaderContract reader, IWriterContract writer, string inputFolder)
{
try
{
Progress(string.Format("Parsing folder {0}...", inputFolder));
string OutputFolder;
// one single output folder
if (!string.IsNullOrEmpty(Settings.DestinationPath) && Directory.Exists(Settings.DestinationPath))
OutputFolder = Settings.DestinationPath;
else
OutputFolder = inputFolder;
DirectoryInfo directory = new DirectoryInfo(inputFolder);
if (Settings.InputType == BookType.PDF)
{
ConvertLoop(reader, writer, OutputFolder, directory, "*.pdf");
}
if (Settings.InputType == BookType.ZIPBased)
{
ConvertLoop(reader, writer, OutputFolder, directory, "*.cbz");
ConvertLoop(reader, writer, OutputFolder, directory, "*.zip");
}
if (Settings.InputType == BookType.RARBased)
{
ConvertLoop(reader, writer, OutputFolder, directory, "*.cbr");
ConvertLoop(reader, writer, OutputFolder, directory, "*.rar");
}
if (Settings.InputType == BookType.XPS)
{
ConvertLoop(reader, writer, OutputFolder, directory, "*.xps");
}
foreach (DirectoryInfo dir in directory.GetDirectories("*", SearchOption.TopDirectoryOnly))
{
if (CancelPending()) return;
ConvertDirectoryRecursively(reader, writer, dir.FullName);
}
}
catch (Exception error)
{
ExceptionHelper.Manage("BookFileConverter:ConvertDirectoryRecursively", error);
Settings.Result = false;
}
finally
{
}
}
private void ConvertLoop(IReaderContract reader, IWriterContract writer, string OutputFolder, DirectoryInfo directory, string fileExtension)
{
if (CancelPending()) return;
foreach (FileInfo file in directory.GetFiles(fileExtension))
{
if (CancelPending())
return;
ConvertFile(reader, writer, file.FullName, OutputFolder);
}
}
/// <summary>
/// convert one file to an output folder regarding the settings mode
/// </summary>
/// <param name="inputfile"></param>
/// <param name="outputFolder"></param>
private void ConvertFile(IReaderContract reader, IWriterContract writer, string inputFile, string outputParam)
{
List<byte[]> imageBytes = new List<byte[]>();
List<string> imageNames = new List<string>();
try
{
Progress(string.Format("Converting {0}...", inputFile));
string outputFolder, tmpFolderForReader = null;
// one single output folder or same as input
if (!string.IsNullOrEmpty(Settings.DestinationPath) && Directory.Exists(Settings.DestinationPath))
outputFolder = Settings.DestinationPath;
else
outputFolder = outputParam;
// particular case to win time
if (Settings.InputType == BookType.ZIPBased || Settings.InputType == BookType.RARBased)
{
if (Settings.OutputType == BookType.ImageFile) //direct in ouput
tmpFolderForReader = outputFolder;
if (Settings.OutputType == BookType.ZIPBased) //use temp folder for compress
tmpFolderForReader = Path.Combine(DirectoryHelper.ApplicationPath, Path.GetFileNameWithoutExtension(inputFile));
}
if(reader.Read(inputFile, tmpFolderForReader, imageBytes, imageNames, Settings, Progress))
writer.Write(Path.GetFileNameWithoutExtension(inputFile), null, outputFolder, imageBytes, imageNames, Settings, Progress);
}
catch (Exception error)
{
ExceptionHelper.Manage("BookFileConverter:ConvertFile", error);
Settings.Result = false;
}
finally
{
if( imageBytes != null )
imageBytes.Clear();
if (imageNames != null)
imageNames.Clear();
}
}
private void ConvertFolder(IReaderContract reader, IWriterContract writer, string inputParam, string outputParam)
{
List<byte[]> imageBytes = new List<byte[]>();
List<string> imageNames = new List<string>();
try
{
Progress( string.Format( "Converting folder {0}...", inputParam) );
string outputFolder, outputFile;
// one single output folder or same as input
if (!string.IsNullOrEmpty(Settings.DestinationPath) && Directory.Exists(Settings.DestinationPath))
outputFolder = Settings.DestinationPath;
else
outputFolder = outputParam;
outputFile = inputParam.Split( new char[] { '\\' } ).Last();
bool result = true;
//only case we need folder input in memory, else we write directly
if (Settings.OutputType == BookType.XPS)
result = reader.Read(inputParam, null, imageBytes, imageNames, Settings, Progress);
if( result )
writer.Write(outputFile, inputParam, outputFolder, imageBytes, imageNames, Settings, Progress);
}
catch (Exception error)
{
ExceptionHelper.Manage("BookFileConverter:ConvertFolder", error);
Settings.Result = false;
}
finally
{
if( imageBytes != null )
imageBytes.Clear();
if (imageNames != null)
imageNames.Clear();
}
}
#endregion
}
}