﻿/***********************************************************************************************************
* $$FileName		ePub Generator.jsx
*
* $$Description		This is the script file which shows an UI for ePub generation
*
* $$Author          	Praful Jain
*
* Copyright (c) 2010 Adobe Systems Incorporated. All Rights Reserved.
************************************************************************************************************/


var mainDlg;

//load all the information
var OPF_TITLE;
var OPF_AUTHOR;
var OPF_PUBLISHER;
var OPF_RIGHTS;
var OPF_DESCRIPTION;
var OPF_TAG;
var OPF_UUID;
var OPF_PUB_DATE;
var OPF_LANG;
var OPF_COVER_PAGE;
var OPF_SOURCE;
var strZipLocation;
var userOutputFolder;
var outputFolder;
var currentProject;
var inputFolder;
var strTOCOutputXML;
var ncxFile;
var org_ncxFile;
var strManifest;
var strSpine;
var spinePendingList;
var batFile;
var bOpenEpubOutput;
var szCurrentXMLSSLName;

//Variables for NCX file
var CONTENT = "content";
var NCX = "ncx";
var ID = "id";
var SOURCE = "src";
var PLAY_ORDER = "playOrder";
var PAGE = "page";
var BOOK = "book";
var TITLE = "title";
var URL = "url";
var META_INF = "META-INF";
var CONTAINER_FILE = "container.xml";
var MIMETYPE = "mimetype";
var OPS_FOLDER = "OPS";
var OPF_FILENAME_TEMP = "content.opf.xml";
var OPF_FILENAME = "content.opf";
var NCX_FILENAME_TEMP = "toc.ncx.xml";
var NCX_FILENAME = "toc.ncx";
var coverId = "_D3589DEB_AABE3B35";
var coverImageFileName = "cover"+coverId+".jpg";
var coverPageHTMLFileName ="cover"+coverId+".htm";
var coverPageId = "coverid"+coverId;
var EPUBCONFXMLFILE = "\\RH_EPUB.xml";

var nPlayOrder = 1;

//this is the main UI dialog string
var mainDlgResource = "dialog {	\
	properties: { closeButton: false },	\
	text:'Generate ePub Output',	\
	g_Output: Group {	\
		    st: StaticText {	\
			    text:'ePub Output Location:'	\
		    },	\
		    et: EditText { \
			    characters: 50	\
		    },	\
		    btn: Button{	\
			    text: 'Browse'	\
		    }	\
	},	\
	g_XMLSSL: Group { orientation: 'row',  alignment: ['fill', 'bottom'], \
		st: StaticText {	\
			text:'Select XML output SSL:'	\
		},	\
		ddl_xml: DropDownList { alignment: ['fill', 'center']} \
	},	\
	tabnav: Panel {	\
		type:'tabbedpanel',	\
		minimumSize:[500, 250],	\
		metaTab: Panel {	\
				type:'tab', text:'Metadata',	\
				orientation: 'column',	\
				alignChildren:'right',	\
				g_Title: Group {	\
					st: StaticText {	\
						text:'Title:'	\
					},	\
					et: EditText {	\
						characters: 60	\
					}	\
				},	\
				g_Author: Group {	\
					st: StaticText {	\
						text:'Author(s):'	\
					},	\
					et: EditText {	\
						characters: 60	\
					}	\
				},	\
				g_Publisher: Group {	\
					st: StaticText {	\
						text:'Publisher(s):'	\
					},	\
					et: EditText {	\
						characters: 60	\
					}	\
				},	\
				g_Tag: Group {	\
					st: StaticText {	\
						text:'Tag:'	\
					},	\
					et: EditText {	\
						helpTip:'Enter tags as comma-separated values.',	\
						characters: 60	\
					}	\
				},	\
				g_Right: Group {	\
					st: StaticText {	\
						text:'Rights:'	\
					},	\
					et: EditText {	\
						characters: 60	\
					}	\
				},	\
				g_Description: Group {	\
					st: StaticText {	\
						text:'Description:'	\
					},	\
					et: EditText {	\
						characters: 60	\
					}	\
				},	\
				g_ISBN: Group {	\
					st: StaticText {	\
						text:'ISBN:'	\
					},	\
					et: EditText {	\
						characters: 60	\
					}	\
				},	\
				g_PublishDate: Group {	\
					st: StaticText {	\
						text:'Publish Date:'	\
					},	\
					et: EditText {	\
                           helpTip:'Enter date as YYYY-MM-DD.',	\
						characters: 60	\
					}	\
				},	\
				g_Language: Group {	\
					st: StaticText {	\
						text:'Language:'	\
					},	\
					et: EditText {	\
						characters: 60	\
					}	\
				}	\
			},	\
		coverTab: Panel {	\
			type:'tab', text:'Cover Page',	\
			coverImage: Image {	\
				size:[350,260],	\
				title:'Cover Page Image Preview',	\
				helpTip:'Cover Page Image Preview',	\
				titleLayout: Object {	\
					alignment:['center','top']	\
					}	\
			},	\
			g_ImageLocation: Group{	\
				st: StaticText {	\
						text:'Image Location:'	\
				},	\
				et: EditText {	\
					characters: 40	\
				},	\
				btn: Button{	\
					text: 'Browse'	\
				}	\
			}	\
		},	\
		zipTab: Panel {	\
			type:'tab', text:'Zip Location',	\
			g_Zip: Group {	\
				st: StaticText {	\
					text:'Zip Location:'	\
				},	\
				et: EditText {	\
					characters: 40	\
				},	\
				btn: Button{	\
					text: 'Browse'	\
				}	\
			},	\
			g_ZipDownload: Group {	\
                st: StaticText { \
                    text:'Zip can be downloaded from  http://stahlforce.com/dev/zip.exe'	\
			    }	\
			    btn: Button{	\
					    text: 'Open in browser'	\
				    }	\
			},	\
		}	\
	},	\
	btnGroup: Group {									\
		alignment:['right', 'bottom'],	\
		chkOpenEpub: Checkbox {text:'Open ePub in default application'},\
		okBtn: Button {	\
			text:'Generate'		\
		},												\
		cancelBtn: Button { 							\
			text:'Close'	\
		}												\
	}			\
}	";

//start the fun now
main();

function main() {
    if (isValidType(RoboHelp)) {
        //check for the project open
        currentProject = RoboHelp.getCurrentProject();
        if (isValidType(currentProject)) {
            //we need to show the main dialog now
            showMainDialog();
        }
        else {
            alert("Please open project");
        }
    }
    else {
        alert("Please launch RoboHelp HTML");
    }
}

function readFile(szFilePath) {
    //if it is RH9 then we will use the readWholeFile function
    if (IsRoboHelp9OrLater()) {
        return RoboHelp.readWholeFile(szFilePath); //this takes care of BOM, encoding and all
    }
    else {
        var szRetVal = "";
        var fileObj = new File(szFilePath);
        fileObj.open("r");
        while (!fileObj.eof) {
            szRetVal += fileObj.readln();
        }
        fileObj.close();
        return szRetVal;
    }
}

function writeToFile(szFilePath, szOutput, bWriteUsingNewFunction) {
    var bSuccess = false;
    if (bWriteUsingNewFunction && IsRoboHelp9OrLater()) {
        bSuccess = RoboHelp.writeWholeFile(szFilePath, szOutput); //this takes care of BOM and encoding as well.
    }

    if (!bSuccess) {
        var fileObj = new File(szFilePath);
        fileObj.open("w");
        fileObj.write(szOutput);
        fileObj.close();
    }
}

function AddEventHandlers() {
    mainDlg.btnGroup.okBtn.onClick = OnGenerateBtnClick;
    mainDlg.tabnav.zipTab.g_Zip.btn.onClick = OnBrowseZipPathClick;
    mainDlg.tabnav.zipTab.g_ZipDownload.btn.onClick = OnOpenZipURLInBrowserClick;
    mainDlg.tabnav.coverTab.g_ImageLocation.btn.onClick = OnBrowseCoverImagePathClick;
    mainDlg.tabnav.coverTab.coverImage.onDraw = drawCoverImage;
    mainDlg.g_Output.btn.onClick = onBrowseEPubOutputClick;
}

function drawCoverImage(drawStateObj) {
    try {
        /* Fit the selected image to the size of the coverImage. 'this'
        is the coverImage object. */
        if (this.image) {
            var imageWidth = this.image.size.width;
            var imageHeight = this.image.size.height;
            var aspectRatio = imageWidth / imageHeight;
            //also check if the size is less
            if (this.size.width <= imageWidth && this.size.height <= imageHeight) {
                if (aspectRatio >= 1.0) {
                    imageWidth = this.size.width;
                    imageHeight = this.size.height / aspectRatio;
                }
                else {
                    imageHeight = this.size.height;
                    imageWidth = this.size.width / aspectRatio;
                }
            }
            else {
                //image selected is small one, so no change in image height and width now
            }
            this.graphics.drawImage(this.image, 0, 0, imageWidth, imageHeight);
        }
    }
    catch (err) {
        // Disable 'onDraw' handling if an error occurs
        this.onDraw = undefined;
    }
}

function showMainDialog() {
    ClearOutputViewLog();
    mainDlg = new Window(mainDlgResource);

    //set close button as cancel button now
    mainDlg.cancelElement = mainDlg.btnGroup.cancelBtn;

    //set the generate button command handler
    AddEventHandlers();

    //we need to load the xml output SSL dialog now
    LoadXMLDDList();

    //we need to load all the saved values as well
    LoadAllSavedInformation();
    mainDlg.show();
}

function LoadXMLDDList() {
    var sslManager = currentProject.SSLManager;
    var nCount = sslManager.count;
    for (var i = 1; i <= nCount; i++) {
        var ssl = sslManager.item(i);
        if (ssl.layoutType == RoboHelp.SSLLayoutType.XMLOUTPUT) {
            //this is XML output, add this to DD
            mainDlg.g_XMLSSL.ddl_xml.add("item", ssl.name);
        }
    } 
}

function isEmptyString(szString) {
    var bRetVal = true;
    if (isValidType(szString)) {
        szString = trim(szString);
        bRetVal = szString.length == 0;
    }
    return bRetVal;
}

function FilePathExists(szFile) {
    var bRetVal = false;
    if (!isEmptyString(szFile)) {
        //check if the file exists or not
        var file = new File(szFile);
        if (isValidType(file)) {
            bRetVal = file.exists;
        }
    }
    return bRetVal;
}

function trim(szString) {
    return szString.replace(/^\s+|\s+$/g, "");
}

function IsValidZipFilePath(szPath) {
    var bRetVal = !isEmptyString(szPath) && FilePathExists(szPath);
    if (bRetVal) {
        bRetVal = false;
        szPath = szPath.toLowerCase();
        var szInputPath = szPath;
        if (szInputPath.length > 7) {
            szPath = szInputPath.substr(szInputPath.length - 7);
            if (szPath == "zip.exe") {
                bRetVal = true;
            }
        }
    }
    return bRetVal;
}

function ValidateAllInputs() {
    var bRetVal = false;
    //first check zip file path
    var szFilePath = mainDlg.tabnav.zipTab.g_Zip.et.text;
    var szOutputFile = mainDlg.g_Output.et.text;
    //check if this file exists or not
    bRetVal = IsValidZipFilePath(szFilePath);
    if (bRetVal) {
        //check for output file location
        if (isEmptyString(szOutputFile) || !FilePathExists(szOutputFile)) {
            //
            bRetVal = false;
            Window.alert("Please specify Output File Path");
            mainDlg.g_Output.et.active = true;
        }
    }
    else {
        //we need to show alert now
        Window.alert("Please specify Zip exe file path");
        mainDlg.tabnav.zipTab.g_Zip.et.active = true;
        mainDlg.tabnav.selection = mainDlg.tabnav.zipTab;
    }
    return bRetVal;
}

function OnOpenZipURLInBrowserClick() {
    var tempFolder = Folder.temp;
    var batchFile = new File(tempFolder.fsName + "\\2C19034A-F44E-41af-BF3A-10879747CB24.bat");     //temp file name
    var strCommand = "start http://stahlforce.com/dev/zip.exe \nexit";
    writeToFile(batchFile.fsName, strCommand, false);
    //run this batch file to open the URL in browser
    batchFile.execute();
}

function OnBrowseZipPathClick() {
    var file = new File(mainDlg.tabnav.zipTab.g_Zip.et.text);
    if (!FilePathExists(mainDlg.tabnav.zipTab.g_Zip.et.text)) {
        file = new File(mainDlg.tabnav.zipTab.g_Zip.et.text);
    }

    var selectedFile = file.openDlg("Select Zip exe file path", "Zip Exe:zip.exe");
    if (isValidType(selectedFile)) {
        mainDlg.tabnav.zipTab.g_Zip.et.text = selectedFile.fsName;
    }
    return isValidType(selectedFile);
}

function UpdateCoverImage() {
    var szImagePath = mainDlg.tabnav.coverTab.g_ImageLocation.et.text;
    if (FilePathExists(szImagePath)) {
        mainDlg.tabnav.coverTab.coverImage.image = ScriptUI.newImage(szImagePath);
    }
}

function onBrowseEPubOutputClick() {
    var folder = new Folder(mainDlg.g_Output.et.text);
    var selectedFolder = folder.selectDlg("Select ePub File Output Location");
    if (isValidType(selectedFolder)) {
        mainDlg.g_Output.et.text = selectedFolder.fsName;
    }
    return isValidType(selectedFile);
}

function OnBrowseCoverImagePathClick() {
    var file = new File(mainDlg.tabnav.coverTab.g_ImageLocation.et.text);
    var selectedFile = file.openDlg("Select Cover Image File", "Image Files:*.jpg;");
    if (isValidType(selectedFile)) {
        mainDlg.tabnav.coverTab.g_ImageLocation.et.text = selectedFile.fsName;
    }
    UpdateCoverImage();
    return isValidType(selectedFile);
}

function IsRoboHelp9OrLater() {
    //get the RoboHelp version
    var versionString = RoboHelp.version;
    var iVersion = parseInt(versionString);
    return (iVersion >= 9);
}

function getCurrentProjectLanguage() {
    var szRetVal = "en_us";
    if (IsRoboHelp9OrLater()) {
        try {
            szRetVal = RoboHelp.Language.getNameFromID(currentProject.language);
        } catch (e) { }
    }
    return szRetVal;
}

function getCurrentDate() {
    var date = new Date;
    var YYYY = date.getFullYear().toString(); 		// getting the current year
    var DD = date.getDate().toString(); 			    // getting the current Date
    var MM = date.getMonth().toString(); 			// getting the current Month
    if (MM.length == 1) {
        MM = "0" + MM;
    }
    if (DD.length == 1) {
        DD = "0" + DD;
    }
    return YYYY + "-" + MM + "-" + DD;

}

function ReadXMLChild(xml, tagName, TextField, defaultValue) {
    var child = null;
    if (isValidType(xml)) {
        child = xml.child(tagName);
    }
    if (isValidType(child)) {
        TextField.text = child.toString();
    }
    if (isEmptyString(TextField.text)) {
        TextField.text = defaultValue;
    }
}

function SaveAllInformation() {
    //we need to save the zip information in common location,
    var xmloutput = new XML("<epubinfo/>");
    xmloutput.appendChild(GetNewXMLChild("zippath", mainDlg.tabnav.zipTab.g_Zip.et.text));
    xmloutput.appendChild(GetNewXMLChild("openEpub", mainDlg.btnGroup.chkOpenEpub.value));

    //we will use all user data folder for saving zip file path
    var commonFile = Folder.appData.fsName + EPUBCONFXMLFILE;
    writeToFile(commonFile, xmloutput.toXMLString(), true);

    //we need to save the project specific information in the project folder area only
    //we need the currentProject Path
    var projectXMLFile = currentProject.path + EPUBCONFXMLFILE;

    //we need to read all the information now
    xmloutput = new XML("<epubinfo/>");
    var szSSLName = "";
    if (isValidType(mainDlg.g_XMLSSL.ddl_xml.selection)) {
        szSSLName = mainDlg.g_XMLSSL.ddl_xml.selection.toString();
    }
    xmloutput.appendChild(GetNewXMLChild("xmlsslname", szSSLName));
    xmloutput.appendChild(GetNewXMLChild("title", mainDlg.tabnav.metaTab.g_Title.et.text));
    xmloutput.appendChild(GetNewXMLChild("author", mainDlg.tabnav.metaTab.g_Author.et.text));
    xmloutput.appendChild(GetNewXMLChild("publisher", mainDlg.tabnav.metaTab.g_Publisher.et.text));
    xmloutput.appendChild(GetNewXMLChild("tag", mainDlg.tabnav.metaTab.g_Tag.et.text));
    xmloutput.appendChild(GetNewXMLChild("ISBN", mainDlg.tabnav.metaTab.g_ISBN.et.text));
    xmloutput.appendChild(GetNewXMLChild("rights", mainDlg.tabnav.metaTab.g_Right.et.text));
    xmloutput.appendChild(GetNewXMLChild("description", mainDlg.tabnav.metaTab.g_Description.et.text));
    xmloutput.appendChild(GetNewXMLChild("publishdate", mainDlg.tabnav.metaTab.g_PublishDate.et.text));
    xmloutput.appendChild(GetNewXMLChild("language", mainDlg.tabnav.metaTab.g_Language.et.text));
    xmloutput.appendChild(GetNewXMLChild("coverimage", mainDlg.tabnav.coverTab.g_ImageLocation.et.text));
    xmloutput.appendChild(GetNewXMLChild("outputfile", mainDlg.g_Output.et.text));
    writeToFile(projectXMLFile, xmloutput.toXMLString(), true);
}

function LoadAllSavedInformation() {
    var commonFile = Folder.appData.fsName + EPUBCONFXMLFILE;
    var szXML = readFile(commonFile);
    var inputXML = null;
    if (!isEmptyString(szXML)) {
        try {
            inputXML = new XML(szXML);
        } catch (e) { inputXML = null; }
    }
    ReadXMLChild(inputXML, "openEpub", mainDlg.tabnav.zipTab.g_Zip.et, "");
    mainDlg.btnGroup.chkOpenEpub.value = false;
    if (mainDlg.tabnav.zipTab.g_Zip.et.text == "true") {
        mainDlg.btnGroup.chkOpenEpub.value = true;
    }
    mainDlg.tabnav.zipTab.g_Zip.et.text = "";
    ReadXMLChild(inputXML, "zippath", mainDlg.tabnav.zipTab.g_Zip.et, "");
    
    //we need to load the project specific information as well
    //we need the currentProject Path
    var projectXMLFile = currentProject.path + EPUBCONFXMLFILE;
    szXML = readFile(projectXMLFile);
    inputXML = null;
    if (!isEmptyString(szXML)) {
        //we need to load the XML and read all the information now
        try {
            inputXML = new XML(szXML);
        } catch (e) { inputXML = null; }
    }
    //read the XML SSL value as well
    ReadXMLChild(inputXML, "xmlsslname", mainDlg.tabnav.metaTab.g_Title.et, "");
    var szSSLName = mainDlg.tabnav.metaTab.g_Title.et.text;
    mainDlg.tabnav.metaTab.g_Title.et.text = "";
    
    ReadXMLChild(inputXML, "title", mainDlg.tabnav.metaTab.g_Title.et, currentProject.name);
    ReadXMLChild(inputXML, "author", mainDlg.tabnav.metaTab.g_Author.et, "");
    ReadXMLChild(inputXML, "publisher", mainDlg.tabnav.metaTab.g_Publisher.et, "");
    ReadXMLChild(inputXML, "tag", mainDlg.tabnav.metaTab.g_Tag.et, "");
    ReadXMLChild(inputXML, "ISBN", mainDlg.tabnav.metaTab.g_ISBN.et, "");
    ReadXMLChild(inputXML, "rights", mainDlg.tabnav.metaTab.g_Right.et, "");
    ReadXMLChild(inputXML, "description", mainDlg.tabnav.metaTab.g_Description.et, "");
    ReadXMLChild(inputXML, "publishdate", mainDlg.tabnav.metaTab.g_PublishDate.et, getCurrentDate());
    ReadXMLChild(inputXML, "language", mainDlg.tabnav.metaTab.g_Language.et, getCurrentProjectLanguage());
    ReadXMLChild(inputXML, "coverimage", mainDlg.tabnav.coverTab.g_ImageLocation.et, "");
    ReadXMLChild(inputXML, "outputfile", mainDlg.g_Output.et, "");
    //we need to select the ssl name from drop down list now
    UpdateXMLSSLSelection(mainDlg.g_XMLSSL.ddl_xml, szSSLName);

    UpdateCoverImage();
}

function UpdateXMLSSLSelection(dropdownControl,szSSLName) {
    var currentSelectionIndex = 0;
    for (var index = 0; index < dropdownControl.children.length; index++) {
        if (dropdownControl.children[index].toString() == szSSLName) {
            currentSelectionIndex = index;
            break;
        }
    }
    dropdownControl.selection = dropdownControl.children[index];
}

function GetNewXMLChild(tagName, tagValue) {
    return new XML("<" + tagName + "><![CDATA[" + tagValue + "]]></" + tagName + ">");
}

function OnGenerateBtnClick() {
    //before going further we need to check if all the things are in place or not
    if (ValidateAllInputs()) {
        //in this case we need to save this information in a file and start the generate process now
        SaveAllInformation();

        //load all the information
        OPF_TITLE = mainDlg.tabnav.metaTab.g_Title.et.text;
        OPF_AUTHOR = mainDlg.tabnav.metaTab.g_Author.et.text;
        OPF_PUBLISHER = mainDlg.tabnav.metaTab.g_Publisher.et.text;
        OPF_RIGHTS = mainDlg.tabnav.metaTab.g_Right.et.text;
        OPF_DESCRIPTION = mainDlg.tabnav.metaTab.g_Description.et.text;
        OPF_TAG = mainDlg.tabnav.metaTab.g_Tag.et.text;
        OPF_UUID = mainDlg.tabnav.metaTab.g_ISBN.et.text;
        OPF_PUB_DATE = mainDlg.tabnav.metaTab.g_PublishDate.et.text;
        OPF_LANG = mainDlg.tabnav.metaTab.g_Language.et.text;
        //we need to replace _ with -
        OPF_LANG = ReplaceString(OPF_LANG, "_", "-");
        OPF_COVER_PAGE = mainDlg.tabnav.coverTab.g_ImageLocation.et.text;
        OPF_SOURCE = OPF_TITLE;
        if (isValidType(mainDlg.g_XMLSSL.ddl_xml.selection)) {
            szCurrentXMLSSLName = mainDlg.g_XMLSSL.ddl_xml.selection.toString();
        }
        strzipLocation = mainDlg.tabnav.zipTab.g_Zip.et.text;
        bOpenEpubOutput = mainDlg.btnGroup.chkOpenEpub.value;
        
        userOutputFolder = mainDlg.g_Output.et.text;
        mainDlg.close(); //hide the main dialog now
        GenerateEPubFormat();
    }
}

function GenerateEPubFormat() {

    ShowMessage("Starting the generation of ePub output now...\n");
    outputFolder = new Folder(userOutputFolder + "\\EPubFolder");
    strTOCOutputXML = "";
    ncxFile = new File(outputFolder.fsName + "\\" + OPS_FOLDER + "\\" + NCX_FILENAME_TEMP);
    org_ncxFile = new File(outputFolder.fsName + "\\" + OPS_FOLDER + "\\" + NCX_FILENAME);
    nPlayOrder = 1;

    //Variables for OPF file

    strManifest = "";
    strSpine = "";
    spinePendingList = new Array();

    batFile = new File(userOutputFolder + "\\zipper.bat");

    strProjectName = currentProject.name;
    if (GenerateOutput()) {
        if (!outputFolder.exists)
            outputFolder.create();

        //we need to clean up the output folder now
        CleanUp(outputFolder, true);
        CreateMetaInfFolder();
        CreateContainerFile();
        CreateOPSFolder();
        CreateNCXFile();
        CreateOPFFile();
        CopyCoverImageFile();
        CreateMimeTypeFile();

        var tempFile = File(userOutputFolder + "\\RoboHelpePub.log");
        if (FilePathExists(tempFile.fsName)) {
            //delete this log file
            tempFile.remove();
        }
        CreateBatFileForZipping();

        var fileEPub = File(userOutputFolder + "\\" + strProjectName + ".epub");

        if (WaitForFinish(tempFile)) {
            $.sleep(1);
            alert("Script executed successfully!");
            ShowMessage("\nePub output generated.");
            if (bOpenEpubOutput) {
                ShowMessage("\nOpening the ePub file in default reader...\n");
                fileEPub.execute(); // Open the generated ePub output automatically through the default application
            }
        }
        else {
            //there was some error
        }
    }
}
function WaitForFinish(tempFile) {
    //we need to show a progress dialog bar now
    ShowMessage("Waiting for Zip to finish compression of ePub file.\n");
    while (!tempFile.exists) // synchronizing the batch file execution
    {
        //ShowMessage(".");
        $.sleep(1);
    }
    tempFile.remove();
    ShowMessage("\nePub file compression completed successfully.\n");
    return true;
}

function GenerateOutput() {
    ShowMessage("Generating XML output...\n");
    strProjectName = currentProject.name;
    var sslManager = currentProject.SSLManager;
    var nCount = sslManager.count;
    var bXMLOutputExists = false;
    for (var i = 1; i <= nCount; i++) {
        var ssl = sslManager.item(i);
        if (ssl.layoutType == RoboHelp.SSLLayoutType.XMLOUTPUT) {
            if (ssl.name == szCurrentXMLSSLName) {
                bXMLOutputExists = true;
                break;
            }
        }
    }

    if (!bXMLOutputExists) {
        alert("XML Output SSL does not exist. Please create one");
        ShowMessage("XML Output SSL does not exist. Please create one\nExiting now.");
    }
    else {
        //the XML SSL is found we need to set the SSL to XHTML type now
        if (IsRoboHelp9OrLater()) {
            var sslFilePath = currentProject.path + "\\" + ssl.name + ".ssl";
            if (!FilePathExists(sslFilePath)|| isEmptyString(ssl.outputFileName)) {
                ssl.generate();
            }
            //in this case we will set the property for XHTML now
            ssl.setSpecificProperty("m_strHandlerMoniker", "Xhtml.hdf|Export Project to XHTML");
            ssl.setSpecificProperty("m_strCustomParams", "");
        }
        var sslOutputFileName = new File(ssl.outputFileName);
        inputFolder = sslOutputFileName.parent;
        //we need to clean up the folder as well now
        CleanUp(inputFolder, true);
        ShowMessage("\nGenerating XML SSL with name \"" + szCurrentXMLSSLName + "\"...\n");
        ssl.generate();
        //once SSL is generated we need to patch the output as well
        PatchXMLOutputNow(inputFolder);
    }
    return bXMLOutputExists;
}

function PatchXMLOutputNow(inputFolder) {
    //we need to traverse all the HTM/HTML Files and patch them one by one
    var listOfFiles = new Array();
    listOfFiles = inputFolder.getFiles("*.*");
    for (; listOfFiles.length > 0; ) {
        var tFile = listOfFiles.pop();
        if (tFile instanceof File) {
            //check the file extension
            var strFileExtension = FileExtension(tFile.displayName);
            if (strFileExtension == ".htm" || strFileExtension == ".html") {
                //if it is HTML file now start patching process
                PatchHTMLOutputFileNow(tFile);
            }
        }
        else {
            //in case it is a directory, call recursivly 
            PatchXMLOutputNow(tFile);
        }
    }
}

function PatchHTMLOutputFileNow(tFile) {
    //get the token manager and start the process
    ShowMessage('\nPatching fIle ' + tFile.fsName);
    if (isValidType(tFile)) {
        var tokenmgr = RoboHelp.getTokenManager(tFile.fsName);
        if (isValidType(tokenmgr) && tokenmgr.count > 0) {
            var bSave = false;
			var bObjectTagStart=false;
            var token = tokenmgr.item(1);
			var strTokenName = token.name;
			strTokenName = strTokenName.toLowerCase();
			var strVideoTag="";
            while (isValidType(token)) {
                //patch for popup links now
                //check if it is anchor or not
                if (token.tokenType == RoboHelp.TokenType.TOKENTAG ) {
                    if(token.tagType == RoboHelp.TagType.TAGOBJECT) {
						//try to get the type now
						var strObjectType = token.getAttribute('type');
						if(strObjectType.indexOf('video/')==0)
						{
							//this is a video type, we should remove this tag and all others till we find the end of object
							bObjectTagStart = true;
							//now add the video tag
							var strVideoSrc = token.getAttribute('data');
							var strWidth = token.getAttribute('width');
							var strHeight = token.getAttribute('height');
							var strWidthHeight="";
							if(isValidType(strWidth) && strWidth.length>0)
							{
								strWidthHeight += " width=\""+strWidth+"\" ";
							}
							if(isValidType(strHeight) && strHeight.length>0)
							{
								strWidthHeight += " height=\""+strHeight+"\" ";
							}
							var strVideoTag = "<video controls=\"controls\" "+strWidthHeight+">";
							strVideoTag += "<source src=\""+strVideoSrc+"\" type=\""+strObjectType+"\"/></video>";
						}
                        bSave = true;
                    }
                    if(token.tagType == RoboHelp.TagType.TAGDIV) {
                        token.removeAttribute("align");
                        bSave=true;
                    }
                    if(token.tagType == RoboHelp.TagType.TAGTABLE) {
                        token.removeAttribute("align");
                        bSave=true;
                    }
                    else if(token.tagType == RoboHelp.TagType.TAGIMAGE) {
                        token.removeAttribute("border");
                        token.removeAttribute("align");
                        token.removeAttribute("name");
                        bSave=true;
                    }
                    else if(token.tagType == RoboHelp.TagType.TAGPARAGRAPH) {
                        token.removeAttribute("align");
                        bSave=true;
                    }
                    else if(token.tagType == RoboHelp.TagType.TAGOL) {
                        token.removeAttribute("type");
                        token.removeAttribute("start");
                        bSave=true;
                    }
                    else if(token.tagType == RoboHelp.TagType.TAGUL) {
                        token.removeAttribute("type");
                        token.removeAttribute("start");
                        bSave=true;
                    }
                    else if(token.tagType == RoboHelp.TagType.TAGSCRIPT) {
                        token.removeAttribute("language");
                        bSave=true;
                    }
                    else if(token.tagType == RoboHelp.TagType.TAGTABLECELL) {
                        token.removeAttribute("width");
                        token.removeAttribute("bgcolor");
                        bSave=true;
                    }
                    else if(token.tagType == RoboHelp.TagType.TAGLINEBREAK) {
                        token.delete();
                        bSave=true;
                    }
                    else if(token.tagType == RoboHelp.TagType.TAGHR) {
                        token.removeAttribute("align");
                        bSave=true;
                    }
                    else if(token.tagType == RoboHelp.TagType.TAGANCHOR) {
                        //we need to delete name attribute 
                        token.removeAttribute("name");
                        bSave=true;
                        var tokenname = token.getAttribute('href');
                        if (isValidType(tokenname)) {
                            //check if it contains popup link or not
                            var JAVASCRIPT_POPUP_CALL = "javascript:BSSCPopup('";
                            if (tokenname.indexOf(JAVASCRIPT_POPUP_CALL) == 0) {
                                //we found popup, we need to patch it now
                                var endIndex = tokenname.indexOf("'", JAVASCRIPT_POPUP_CALL.length + 1);
                                if (endIndex != -1) {
                                    var linkName = tokenname.substr(JAVASCRIPT_POPUP_CALL.length, endIndex - JAVASCRIPT_POPUP_CALL.length);
                                    token.setAttribute('href', linkName);
                                }
                            }
                        }
                    }
					if(bObjectTagStart && token.tagType == 268567088)
					{
						token.delete();
						bObjectTagStart = false;
						token.insertText(strVideoTag,true);
					}
                }
				
				if(bObjectTagStart)
				{
					token.delete();
					bSave=true;
				}
                //we need to remove CData from HTML as well
                if (token.name.indexOf('//<![CDATA[') != -1) {
                    token.delete();
                    bSave = true;
                }
				

                token = token.next;
            }
            if (bSave) {
                tokenmgr.save();
            }
        }
    }
}

function CreateMimeTypeFile() {
    ShowMessage("Creating mime-type file...\n");
    var mimeTypeFile = new File(outputFolder.fsName + "\\" + MIMETYPE);
    var strText = "application/epub+zip";
    writeToFile(mimeTypeFile.fsName, strText, false);
}

function CreateMetaInfFolder() {
    ShowMessage("Creating meta-inf folder...\n");
    var folderMetaInf = new Folder(outputFolder.fsName + "\\" + META_INF);
    if (!folderMetaInf.exists)
        folderMetaInf.create();
}

function CreateContainerFile() {
    ShowMessage("Creating container file...\n");
    var containerFile = new File(outputFolder.fsName + "\\" + META_INF + "\\" + CONTAINER_FILE);
    var strXML = "<?xml version=\"1.0\"?>";
    strXML += "<container version=\"1.0\" xmlns=\"urn:oasis:names:tc:opendocument:xmlns:container\">";
    strXML += "<rootfiles><rootfile full-path=\"OPS/" + OPF_FILENAME + "\" media-type=\"application/oebps-package+xml\"/></rootfiles>";
    strXML += "</container>";

    writeToFile(containerFile.fsName, strXML, false);
}

function CreateOPSFolder() {
    ShowMessage("Creating OPS folder...\n");
    var folderOPSInf = new Folder(outputFolder.fsName + "\\" + OPS_FOLDER);
    if (!folderOPSInf.exists)
        folderOPSInf.create();

	ShowMessage("Copying files now...\n");
    var listOfFiles = new Array();
    listOfFiles = inputFolder.getFiles("*.*");
    for (; listOfFiles.length > 0; ) {
        tFile = listOfFiles.pop();
        if (tFile instanceof File) {
            var name = tFile.displayName;
            var prjname = currentProject.name;
            if (name == (prjname + ".xml") || name == (prjname + "_toc.xml") || name == (prjname + "_brs.xml") || name == (prjname + "_gls.xml") || name == (prjname + "_prj.xml")
				|| name == (prjname + "_csh.xml") || name == (prjname + "_ndx.xml") || name == (prjname + "_sls.xml")) continue;
            if (FileExtension(name) == ".log" || name == "ehlpdhtm.js") continue;
            tFile.copy(folderOPSInf.fsName.concat("\\", tFile.displayName));
        }
        else {
            var tempFolder = Folder(folderOPSInf.fsName.concat("\\", tFile.displayName));
            if (tempFolder.exists == false) tempFolder.create();
            CopyFolder(tFile, tempFolder);
        }
    }
}

function CopyCoverImageFile() {
    //in the end we need to copy the cover image file if it exists
    if (FilePathExists(OPF_COVER_PAGE)) {
        ShowMessage("Copying cover image file...\n");
        var coverimage = new File(OPF_COVER_PAGE);
        var folderOPSInf = new Folder(outputFolder.fsName + "\\" + OPS_FOLDER);
        var outputImage = folderOPSInf.fsName + "\\" + coverImageFileName;
        coverimage.copy(outputImage);
		//create cover HTML file now
		CreateCoverHTMLFile();
    }
}

function CreateCoverHTMLFile(){
var coverPageHTMLContent =  '<?xml version="1.0" encoding="utf-8"?>'+
							'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'+
							'<html xmlns="http://www.w3.org/1999/xhtml">'+
								'<head>'+
									'<meta content="application/xhtml+xml; charset=utf-8" http-equiv="Content-Type"/>'+
									'<title>Cover Page</title>'+
									'<style type="text/css"> img { max-width: 100%; } </style>'+
								'</head>'+
								'<body style="margin: 0; padding: 0;">'+
									'<div id="cover-image">'+
										'<img alt="Cover Page Image" src="'+coverImageFileName+'"/>'+
									'</div>'+
								'</body>'+
							'</html>';
	
	var folderOPSInf = new Folder(outputFolder.fsName + "\\" + OPS_FOLDER);
	var coverHTMLFile = new File(folderOPSInf.fsName+"\\"+coverPageHTMLFileName);
	writeToFile(coverHTMLFile.fsName,coverPageHTMLContent,true);
}

function CreateOPFFile() {
    ShowMessage("Creating OPF file...\n");
    var containerFile = new File(outputFolder.fsName + "\\" + OPS_FOLDER + "\\" + OPF_FILENAME_TEMP);
    var org_containerFile = new File(outputFolder.fsName + "\\" + OPS_FOLDER + "\\" + OPF_FILENAME);
    var strXML = "";
    strXML += "<package xmlns=\"http://www.idpf.org/2007/opf\" unique-identifier=\"EPB-UUID\" version=\"2.0\">";
    strXML += "    <metadata xmlns:opf=\"http://www.idpf.org/2007/opf\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">";
    strXML += "       <dc:title>" + OPF_TITLE + "</dc:title>";
    strXML += "       <dc:creator opf:role=\"aut\" opf:file-as=\"" + OPF_AUTHOR + "\">" + OPF_AUTHOR + "</dc:creator>";
    strXML += "       <dc:publisher>" + OPF_PUBLISHER + "</dc:publisher>";
    strXML += "       <dc:date opf:event=\"epub-publication\">" + OPF_PUB_DATE + "</dc:date>";
    strXML += "       <dc:source>" + OPF_SOURCE + "</dc:source>";
    strXML += "       <dc:rights>" + OPF_RIGHTS + "</dc:rights>";
    strXML += "       <dc:description>" + OPF_DESCRIPTION + "</dc:description>";
    strXML += "       <dc:identifier id=\"EPB-UUID\">" + OPF_UUID + "</dc:identifier>";
    strXML += "       <dc:language>" + OPF_LANG + "</dc:language>";
    //we need to add the tags now <dc:subject>
    if (!isEmptyString(OPF_TAG)) {
        var tagArray = OPF_TAG.split(",");
        for (var iTag = 0; iTag < tagArray.length; iTag++) {
            //add tag now
            var tagEntry = tagArray[iTag];
            if (!isEmptyString(tagEntry)) {
                strXML += "       <dc:subject>" + tagEntry + "</dc:subject>";
            }
        }
    }
    //we need to check if the cover image is there or not
    if (FilePathExists(OPF_COVER_PAGE)) {
        //if the cover image exists then we need to create the entry here for that image now
        strXML += "<meta name=\"cover\" content=\"cover-image\"/>";
    }

    strXML += "   </metadata>";
    strXML += "   <manifest>";
    if (FilePathExists(OPF_COVER_PAGE)) {
        //if the cover image is present then create that entry as well
        //we save the cover image with a unique name an ID, so that it does not interfre with the other image names
        strXML += "   <item id=\"cover-image\" href=\"" + coverImageFileName + "\" media-type=\"image/jpeg\"/>";
		strXML += "   <item id=\""+coverPageId+"\" href=\"" + coverPageHTMLFileName + "\" media-type=\"application/xhtml+xml\"/>";
    }

    var folderOPSInf = new Folder(outputFolder.fsName + "\\" + OPS_FOLDER);

    var parentFoldername = "";
    createOPFText(folderOPSInf, parentFoldername);
    strXML += strManifest;
    strXML += "   </manifest>";
    strXML += "   <spine toc=\"ncx\">";
	if (FilePathExists(OPF_COVER_PAGE)) {
		 strXML += "<itemref idref=\""+coverPageId+"\" linear=\"no\"/>";
	}
    UpdateSpineWithPendingData();
    strXML += strSpine;
    strXML += "   </spine>";
    //we need to check if the cover image is there or not
    if (FilePathExists(OPF_COVER_PAGE)) {
        //if the cover image exists then we need to create the entry here for that image now
        strXML+="<guide>";
		strXML+="<reference href=\""+coverPageHTMLFileName+"\" title=\"Cover page\" type=\"cover\" />";
		strXML+="</guide>";
    }
    strXML += " </package>";

    writeToFile(containerFile.fsName, GenerateXMLOutput(strXML), true);
    //we need to move the xml file to original file now
    containerFile.rename(org_containerFile.fsName);
}

function GenerateXMLOutput(szOutput) {
    var szRetVal = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";    //start of XML file
    var xml = new XML(szOutput);
    return szRetVal + xml.toXMLString();
}

function ReplaceString(szStringToBeReplaced, szStringToSearch, szStringToReplace) {
    try {
        if (isValidType(szStringToBeReplaced) && isValidType(szStringToSearch) && isValidType(szStringToReplace)) {

            var myPattern = new RegExp(szStringToSearch, "gi");
            return szStringToBeReplaced.replace(myPattern, szStringToReplace);
        }
    } catch (e) {
        ShowMessage('Error While calling Replace String function check the string');
    }
    return szStringToBeReplaced;
}

function EscapeAllXMLValues(szTemp) {
    if (!isEmptyString(szTemp)) {
        // special handling for XML restricted characters - Begins //
        szTemp = ReplaceString(szTemp, "&", "&amp;");
        szTemp = ReplaceString(szTemp, "<", "&lt;");
        szTemp = ReplaceString(szTemp, ">", "&gt;");
        szTemp = ReplaceString(szTemp, "'", "&apos;");
        //szTemp = ReplaceString(szTemp, "‘", "&apos;");
        //szTemp = ReplaceString(szTemp, "’", "&apos;");
        //szTemp = ReplaceString(szTemp, "“", "&quot;");
        //szTemp = ReplaceString(szTemp, "”", "&quot;");
        szTemp = ReplaceString(szTemp, "\"", "&quot;");
    }
    // special handling for XML restricted characters - ends //
    return szTemp;
}

function PatchXMLIDAttribute(strID) {
    if (!isEmptyString(strID)) {
        // special handling for XML restricted characters - Begins //
        strID = trim(strID);
        strID = strID.replace(/^\s+|\s+$/g, "_");
        strID = strID.replace(/[\/]/g, '_');
        strID = strID.replace(/%\w\w/g, '_');
        if (strID.match(/^(\d+)/g) > 0) {
            strID = 'ID-' + strID;
        }
        strID = ReplaceString(strID, " ", "_");
        strID = ReplaceString(strID, "&", "_");
        strID = ReplaceString(strID, "<", "_");
        strID = ReplaceString(strID, ">", "_");
        strID = ReplaceString(strID, "'", "_");
        strID = ReplaceString(strID, "‘", "_");
        strID = ReplaceString(strID, "’", "_");
        strID = ReplaceString(strID, "“", "_");
        strID = ReplaceString(strID, "”", "_");
        strID = ReplaceString(strID, "\"", "_");
        // special handling for XML restricted characters - ends //
    }
    return strID;
}

function createOPFText(folderOPSInf, parentFoldername) {
    var listOfFiles = new Array();
    listOfFiles = folderOPSInf.getFiles("*.*");
    for (; listOfFiles.length > 0; ) {
        tFile = listOfFiles.pop();
        if (tFile instanceof Folder) {
            var tempFolder = Folder(folderOPSInf.fsName.concat("\\", tFile.displayName));
            createOPFText(tempFolder, parentFoldername + tFile.displayName + "/");
        }
        else {
            var name = tFile.displayName;
            var FileExt = FileExtension(name);
            var id = parentFoldername + name.substr(0, name.length - FileExt.length);
            id = PatchXMLIDAttribute(id);
            var parentFolderPlusFileName = parentFoldername + name;
            parentFolderPlusFileName = EscapeAllXMLValues(parentFolderPlusFileName);


            if (FileExt == ".htm" || FileExt == ".html") //topic
            {
                var newxml = new XML("<item/>");
                strManifest += "        <item id=\"" + id + "\" href=\"" + parentFolderPlusFileName + "\" media-type=\"application/xhtml+xml\"/>";
                AppendSpinePendingList(id);
            }
            else if (FileExt == ".css") {
				strManifest += "        <item id=\"" + id + "_css\" href=\"" + parentFolderPlusFileName + "\" media-type=\"text/css\"/>";
            }
            else if (FileExt == ".js") {
				strManifest += "        <item id=\"" + id + "_js\" href=\"" + parentFolderPlusFileName + "\" media-type=\"text/javascript\"/>";
            }
            else if (FileExt == ".png" || FileExt == ".PNG") {
				strManifest += "        <item id=\"" + id + "_png\" href=\"" + parentFolderPlusFileName + "\" media-type=\"image/png\"/>";
            }
            else if (FileExt == ".jpeg" || FileExt == ".jpg" || FileExt == ".JPG" || FileExt == ".JPEG") {
                strManifest += "        <item id=\"" + id + "_jpg\" href=\"" + parentFolderPlusFileName + "\" media-type=\"image/jpeg\"/>";
            }
            else if (FileExt == ".gif" || FileExt == ".GIF") {
                strManifest += "        <item id=\"" + id + "_gif\" href=\"" + parentFolderPlusFileName + "\" media-type=\"image/gif\"/>";
            }
            else if (FileExt == ".bmp" || FileExt == ".BMP") {
                strManifest += "        <item id=\"" + id + "_bmp\" href=\"" + parentFolderPlusFileName + "\" media-type=\"image/bmp\"/>";
            }
            else if (FileExt == ".ncx") {
                strManifest += "      <item id=\"ncx\" href=\"" + NCX_FILENAME + "\" media-type=\"application/x-dtbncx+xml\"/>";
            }
            else if (FileExt == ".pdf") {
                strManifest += "        <item id=\"" + id + "_pdf\" href=\"" + parentFolderPlusFileName + "\" media-type=\"application/pdf\"/>";
                AppendSpinePendingList(id+"_pdf");
            }
            else if (FileExt == ".swf") {
                strManifest += "        <item id=\"" + id + "_swf\" href=\"" + parentFolderPlusFileName + "\" media-type=\"application/x-shockwave-flash\"/>";
                AppendSpinePendingList(id+"_swf");
            }
			else if(IsSupportedVideoType(FileExt)){
				var supportedMediaType = GetMediaTypeForVideo(FileExt);
				strManifest += "        <item id=\"" + id + "_video\" href=\"" + parentFolderPlusFileName + "\" media-type=\""+supportedMediaType+"\"/>";
			}
            else {
                strManifest += "        <item id=\"" + id + "_txt\" href=\"" + parentFolderPlusFileName + "\" media-type=\"application/text\"/>";
                AppendSpinePendingList(id+"_txt");
            }
        }
    }
}

function GetMediaTypeForVideo(fileExt){
	if(fileExt == '.mpeg' || fileExt == '.mpg')
		return "video/mpeg";
	if(fileExt == '.mp4')
		return "video/mp4";
	if(fileExt == '.ogg')
		return "video/ogg";
	if(fileExt == '.webm')
		return "video/webm";
	if(fileExt == '.wmv')
		return "video/x-ms-wmv";
	if(fileExt == '.avi')
		return "video/x-msvideo";
	if(fileExt == '.m4v')
		return "video/mpeg4";
        
}

function IsSupportedVideoType(fileExt){
	return (	
		fileExt == '.mpeg' ||
        fileExt == '.mpg' ||
		fileExt == '.mp4' ||
        fileExt == '.m4v' ||
		fileExt == '.ogg' ||
		fileExt == '.webm' ||
        fileExt == '.avi' ||
		fileExt == '.wmv');
}

function AppendSpinePendingList(id){
	//first check if this already there or not
	if(!isIDPresentInArray(spinePendingList,id))
	{
		spinePendingList[spinePendingList.length]=id;
	}
}

function UpdateSpineWithPendingData(){
	//we need to check each spine in the pending array and see if it is already there in the spine string or not
	if(isValidType(spinePendingList))
	for(var index=0;index<spinePendingList.length;index++){
		strSpine += "      <itemref idref=\"" + spinePendingList[index] + "\" linear=\"yes\"/>";
	}
}

function isIDPresentInArray(array,value){
	var bFound=false;
	if(isValidType(array))
	{
		for(var index=0;index<array.length;index++){
			if(array[index] == value){
				bFound=true;
				break;
			}
		}
	}
	return bFound;
}

function AppendToTOCXML(strValue) {
    strTOCOutputXML += strValue + "\n";
}

function getTOCFileFromProjectFolder(){
    //first check if the project name file is present or not
    var tocFile = File(inputFolder + "\\" + currentProject.name + "_toc.xml");
    if(!tocFile.exists)
    {
        //now we need to search all the xml file in the inputfolder and see if any one has _toc.xml in it or not
       var folder = new Folder(inputFolder);
       var fileList = folder.getFiles ("*.xml");
       //in these files we need to find the toc File now
       if(isValidType (fileList))
       {
           for(var index=0;index<fileList.length;index++)
           {
               var file = fileList[index];
               var szFileName = file.fsName;
               szFileName = szFileName.toLowerCase();
               if(szFileName.lastIndexOf ("_toc.xml") == szFileName.length-8)
               {
                   tocFile = file;
                   break;
               }    
           }    
       }
    }   
    return tocFile;
}

function CreateNCXFile() {
    ShowMessage("Creating NCX(TOC) file...\n");
    var tocFile = getTOCFileFromProjectFolder();

    if (!isValidType(tocFile) || !tocFile.exists)
        alert("TOC file missing");
    else {
        //we need to write it once only

        AppendToTOCXML("<ncx xmlns=\"http://www.daisy.org/z3986/2005/ncx/\" version=\"2005-1\">");
        AppendToTOCXML("<head>");
        AppendToTOCXML("<meta name=\"dtb:uid\" content=\"jedisaber.com06282007214712\"/>");
        AppendToTOCXML("<meta name=\"dtb:depth\" content=\"1\"/>");
        AppendToTOCXML("<meta name=\"dtb:totalPageCount\" content=\"0\"/>");
        AppendToTOCXML("<meta name=\"dtb:maxPageNumber\" content=\"0\"/>");
        AppendToTOCXML("</head>");

        AppendToTOCXML(GetDocTitle());
        GetTOCEntries(tocFile);
        AppendToTOCXML("</ncx>");


        writeToFile(ncxFile.fsName, GenerateXMLOutput(strTOCOutputXML), true);
        //we need to move the xml file to original file now
        ncxFile.rename(org_ncxFile.fsName);
    }
}

function CreateBatFileForZipping() {
    ShowMessage("Launching Zip to compress ePub file...\n");
    var strText = "cd \"" + outputFolder.fsName + "\"\n";
    //we need to move to that drive as well
    strText += outputFolder.fsName.substr(0, 1) + ":\n";
    strText += "\"" + strzipLocation + "\" -q0X \"" + strProjectName + ".epub\" mimetype\n";
    strText += "\"" + strzipLocation + "\" -qXr9D \"" + strProjectName + ".epub\" META-INF OPS\n";
    //strText += "\"" + strzipLocation + "\" a -tzip \"" + strProjectName + ".epub\" \"" + outputFolder.fsName + "\\*\" \n";
    strText += "move \"" + strProjectName + ".epub\" \"" + userOutputFolder + "\"\n";
    strText += "cd ..\n";
    strText += "rd /S /Q \"" + outputFolder.fsName + "\"\n";
    strText += "echo Generating \"" + userOutputFolder + "\\" + strProjectName + ".epub\">RoboHelpePub.log\n";
    strText += "del /F /Q \"" + batFile.fsName + "\"\n";

    writeToFile(batFile.fsName, strText, false);
    batFile.execute();
}

function GetDocTitle() {
    var strTitle = "<docTitle>";
    strTitle += "<text>";
    strTitle += "Sample ePub Book"; //title to be changed
    strTitle += "</text>";
    strTitle += "</docTitle>";
    return strTitle;
}

function GetTOCEntries(tocFile) {
    AppendToTOCXML("<navMap>");

    var szFileOutput = readFile(tocFile.fsName);
    var tocXML = new XML(szFileOutput);

    var entries = tocXML.children();
    var nLen = entries.length();
    if (nLen == 1) {
        var tNode = entries;
        if (tNode.name() == PAGE) {
            MapPage(tNode, true);
        }
        else if (tNode.name() == BOOK) {
            MapBook(tNode, true);
        }
    }
    else {
        var i = 0;
        for (i = 0; i < nLen; i++) {
            var tNode = entries.child(i);
            if (tNode.name() == PAGE) {
                MapPage(tNode, true);
            }
            else if (tNode.name() == BOOK) {
                MapBook(tNode, true);
            }
        }
    }

    AppendToTOCXML("</navMap>");
}

function MapPage(tNode, bWrite) {
    var strURL = getAttributeFromXML(tNode, URL);
    var strTitle = getAttributeFromXML(tNode, TITLE);
    var nTemp = strURL.lastIndexOf(".");
    var strId = strURL.substr(0, nTemp);
    strId = PatchXMLIDAttribute(strId);

    strTitle = EscapeAllXMLValues(strTitle);

    strURL = EscapeAllXMLValues(strURL);

    var strXML = "<navPoint id=\"" + strId + "\" playOrder=\"" + nPlayOrder + "\">";
    AppendSpinePendingList(strId);
    nPlayOrder++;
    strXML += "<navLabel>";
    strXML += "<text>";
    strXML += strTitle;
    strXML += "</text>";
    strXML += "</navLabel>";
    strXML += "<content src=\"" + strURL + "\"/>";
    strXML += "</navPoint>";

    if (bWrite)
        AppendToTOCXML(XML(strXML).toString());

    return strXML;
}

function MapBook(tBookNode, bWrite) {
    var strTitle = getAttributeFromXML(tBookNode, TITLE);
    var strURL = getAttributeFromXML(tBookNode, URL);
    var bURLFound = isValidType(strURL) && !isEmptyString(strURL);
    var strXML = "";

    var nLocalPlayOrder = nPlayOrder;
    nPlayOrder++;
    var nTemp = strURL.lastIndexOf(".");
    var strId = strURL.substr(0, nTemp);
    strId = PatchXMLIDAttribute(strId);

    if (bURLFound) {
        AppendSpinePendingList(strId);
    }

    var children = tBookNode.children();
    var nLen = children.length();

    if (nLen == 1) {
        var tNode = children;
        if (tNode.name() == PAGE) {
            strXML += MapPage(tNode, false);
            if (!bURLFound) {
                bURLFound = true;
                strURL = getAttributeFromXML(tNode, URL);
            }
        }
        else if (tNode.name() == BOOK) strXML += MapBook(tNode, false);
    }
    else {
        var i = 0;
        for (i = 0; i < nLen; i++) {
            var tNode = children.child(i);
            if (tNode.name() == PAGE) {
                strXML += MapPage(tNode, false);
                if (!bURLFound) {
                    bURLFound = true;
                    strURL = getAttributeFromXML(tNode, URL);
                }
            }
            else if (tNode.name() == BOOK) strXML += MapBook(tNode, false);
        }
    }

    strURL = EscapeAllXMLValues(strURL);

    var strRet = "<navPoint id=\"" + strId + "\" playOrder=\"" + nLocalPlayOrder + "\">";
    strRet += "<navLabel>";
    strRet += "<text>";
    strRet += EscapeAllXMLValues(strTitle);
    strRet += "</text>";
    strRet += "</navLabel>";
    strRet += "<content src=\"" + strURL + "\"/>";
    strRet += strXML;
    strRet += "</navPoint>";

    if (bWrite)
        AppendToTOCXML(XML(strRet).toString());

    return strRet;
}

function FileExtension(filename) {
    var strExtension="";
    var index = filename.lastIndexOf(".");
    if (index != -1) {
        strExtension = filename.substr(index, filename.length - index);
        strExtension = strExtension.toLowerCase();
    }
    return strExtension;
}

function CopyFolder(srcFolder, tarFolder) {
    var listOfFiles = new Array();
    listOfFiles = srcFolder.getFiles("*.*");
    for (; listOfFiles.length > 0; ) {
        tFile = listOfFiles.pop();
        if (tFile instanceof Folder) {
            var tempFolder = Folder(tarFolder.fsName.concat("\\", tFile.displayName));
            if (tempFolder.exists == false) tempFolder.create();
            CopyFolder(tFile, tempFolder);
        }
        else {
            tFile.copy(tarFolder.fsName.concat("\\", tFile.displayName));
        }
    }
}

function CleanUp(folder, deleteRootFolder) {
    if (folder.exists == false) {
        return false;
    }
    var listOfFiles = folder.getFiles("*.*");
    var tFile;

    for (; listOfFiles.length > 0; ) {
        tFile = listOfFiles.pop();
        if (tFile instanceof Folder) {
            CleanUp(tFile, true);
        }
        else {
            tFile.remove();
        }
    }
    if (deleteRootFolder == true) {
        folder.remove();
    }
    if (isValidType(listOfFiles)) {
        delete listOfFiles;
    }
}

function getAttributeFromXML(xml, attributeName) {
    var szRetVal = null;
    if (isValidType(xml)) {
        var attributeValue = xml.attribute(attributeName);
        if (isValidType(attributeValue)) {
            szRetVal = attributeValue.toString();
        }
    }
    return szRetVal;
}

function isValidType(value) {
    if (typeof (value) !== 'undefined' && value != null) {
        return true;
    }
    return false;
}

function ShowMessage(msg) {
    RoboHelp.project.outputMessage(msg);
}

function ClearOutputViewLog() {
    RoboHelp.project.clearOutputViewLog();
}
