/* Copyright 2009 Palm, Inc.  All rights reserved. */
/*global Mojo, Class, $L, Template, WordAssistant, ExcelAssistant, PowerPointAssistant,
 OptionsDialogAssistant:true, SaveAsDialogAssistant:true, CommentsDialogAssistant:true, PropertiesDialogAssistant */
/*jslint rhino:true, undef:true */

var DocumentAssistant = Class.create({

	msgDivPos: 50,

    modesModel: { mode: 'vertical' },

    docViewMenu: [ { template: 'document/header_bar' } ],

    pptViewMenu: [ { template: 'document/header_bar' } ],

    xlsViewMenu: [ { template: 'document/header_bar' } ],

	numericMap: {
		e:'1',r:'2',t:'3',
		d:'4',f:'5',g:'6',
		x:'7',c:'8',v:'9',
			'@':'0',
		
		1:'1',2:'2',3:'3',
		4:'4',5:'5',6:'6',
		7:'7',8:'8',9:'9',
			  0:'0'
	},    

    orientationChanged: function(orientation) {
        //this.fileAssistant.orientationChanged(orientation);
    },

    initialize: function(parameters) {
		
        Mojo.Log.info("DocumentAssistant: initialize: '%s'", Object.toJSON(parameters));

		this.appAssistant = Mojo.Controller.appController.assistant;
		this.showMenuBars = this.showMenuBars.bind(this);
		this.doAutoHide = this.doAutoHide.bind(this);
		this.showError = this.showError.bind(this);
		this.showFootPageOf = this.showFootPageOf.bind(this);
		this.showDocumentProperties = this.showDocumentProperties.bind(this);		
		this.handleFootPage = this.handleFootPage.bind(this);
		this._handleFocus = this._handleFocus.bind(this);
		this.mousecheck = this.mousecheck.bindAsEventListener(this);
		this.lunatap = this.lunatap.bindAsEventListener(this);
		this._showLoadingSpinner = this._showLoadingSpinner.bind(this);
		this._hideLoadingSpinner = this._hideLoadingSpinner.bind(this);
		this._loadingScrim = null;
		this._loadingSpinner = null;
		this._loadingSpinnerTimeout = null;
		this._spinnerShowTime = 0;
		this.propertiesDialogShowing = false;

		// Excel
		this.resizeMode = 'off';

		// PPT
		this.slideShowRunning = false;
		this.notesShowing = false;

		this.pptScrollTop = 168;
		this.pptSize = 50;
		this.sceneActive = true;

		this.autoHideTimeout = undefined;
		this.document_id = undefined;
		this.document_name = undefined;
		this.document_type = undefined;
		this.document_noext = undefined;
		this.errorText = undefined;
		this.propertiesText = undefined;
		this.resultCount = undefined;

		this.excelItems = [
			{ label:$L('Worksheets'), command:'xls-outline' },
			{ label:$L('Resize'), command:'resize-cmd' },
			{ label:$L('Show All Hidden'), command:'xls-showall-cmd' }
		];

		this.wordItems = [ 
			{ label:$L('Wide View'), command:'widemode-cmd' }
		]; 

		this.powerpointItems = [
			{ label:$L('Outline'), command:'ppt-outline' },
			{ label:$L('Show Notes'), command:'ppt-notes' }
		];

		this.menuBottomItems = [
			{ label:$L('Document Editing...'), command:'upgrade-cmd' },
			{ label:$L('Help'), command:Mojo.Menu.helpCmd, checkEnabled:true }
		];

		this.appMenuModel = { visible:true, omitDefaultItems:true,
			items: [
				{ label:$L('Open'), command:'file-open-cmd' },
				{ label:$L('Save As...'), command:'file-saveas-cmd' },
				{ label:$L('Share'), command:'share-cmd' },
				{ label:$L('Find'), command:'find-cmd', chosen:false }
			]};

		this.docPropRunning = false;
		this.doMRU = false;
		this.doSaveMRU = false;
		this.isHidden = false;
		this.initDone = false;
		this.pageHeadEnt = false;
		this.pageFootEdit = false;
		this.pageFootFirst = true;
		this.saveShowing = false;
		this.propertiesShowing = false;
		this.commentsShowing = false;
		this.wasTextDoc = false;
		this.viewMenuVisible = true;
		this.adapter = undefined;
		this.cur_page = 0;
		this.pageCount = undefined;

		this.bottomPosition = -105;
		this.lastScreenClickX = 0;
		this.lastScreenClickY = 0;
		this.openDialog = null;

		this.mruArray = [];
		this.recentList = [];

        // Variables needed for find / search
        this.findShowing = false;
        this.findString = '';
        this.newFindString = '';
        this.findCancel = false;
		this.filename = undefined;
		if (parameters.launchParams && parameters.launchParams.target) {
			this.filename = parameters.launchParams.target;
		}
		else if (parameters.file) {
			this.filename = parameters.file;
		}

		if (this.filename && this.filename.startsWith('file://')) {
			this.filename = this.filename.substr(7);
		}

		Mojo.Log.info("Filename = '%s'", this.filename);
    },

    setup: function() {
		try {

            /*
            if (PalmSystem.setWindowOrientation) {
                PalmSystem.setWindowOrientation("free");
            }
            */
			
			Mojo.Log.info("DocumentAssistant: setup filename('%s')", this.filename);

			var placeholder = this.controller.get('install_object_here');
			this.adapter = this.InstallOfficeAdapter(placeholder);

			this.spinner_id = 'my_spinner';
			this.spinnerRunning = false;

			// Set up the view buttons (header)
			//start of header setup
			
			var viewMenu;
			var launchPage = Mojo.View.render({ template: 'document/header_bar' });
			if (this.document_type == 'doc') {
				//viewMenu = this.docViewMenu;
				this.fileAssistant = new WordAssistant(this);
			}
			else if (this.document_type == 'ppt') {
				//viewMenu = this.pptViewMenu;
				this.fileAssistant = new PowerPointAssistant(this);
			}
			else if (this.document_type == 'xls') {
				//viewMenu = this.xlsViewMenu;
				this.fileAssistant = new ExcelAssistant(this);
			}
			else {
				// viewMenu = [];
			}
			
			// this.viewMenuModel = { visible: true, items: viewMenu };
			// this.controller.setupWidget(Mojo.Menu.viewMenu,
			//							{menuClass:'no-fade'},
			//							this.viewMenuModel);
			this.headerTemplate = this.controller.get('headerTemplate');
			this.headerTemplate.update(launchPage);

			Mojo.Log.info("@@@ HERE 0");
	
			if (this.document_type === 'ppt' || this.document_type === 'xls') {
				// Set up the command buttons (footer)
				var cmdMenu = this.fileAssistant.getCommandMenu();
				this.cmdMenuModel = { visible: false, items: cmdMenu, command: 'cmd-menu-tap' };
				this.controller.setupWidget(Mojo.Menu.commandMenu,
											{menuClass:'no-fade'},
											this.cmdMenuModel);
			}
			else {
				this.cmdMenuModel = undefined;
			}

			this.controller.get('PlugIn').observe(Mojo.Event.flick,
								this.flickcheck.bindAsEventListener(this));

			this.controller.get('PlugIn').observe(Mojo.Event.tap, this.lunatap);

			this.controller.get('PlugIn').observe('mousedown', this.mousecheck);

			this.controller.document.addEventListener('gesturestart',
					this.gestureStart.bindAsEventListener(this), true);

			this.controller.document.addEventListener('gesturechange',
					this.gestureChange.bindAsEventListener(this), true);

			this.controller.document.addEventListener('gestureend',
					this.gestureEnd.bindAsEventListener(this), true);
			
			// this.controller.document.addEventListener('mousedown',
			//		this.handleMouseDown.bindAsEventListener(this), false);

			// Setting up scroll widget for notes dialog
			this.controller.setupWidget('noteScroll', {}, { mode: 'vertical' });

			// Setting up scroll widget for comments dialog
			this.controller.setupWidget('commentScroll', {}, { mode: 'vertical' });

			if (this.document_type == 'xls') {
				this.appMenuModel.items =
					this.appMenuModel.items.concat.apply(this.appMenuModel.items,
														 this.excelItems);
			}
			else if (this.document_type == 'doc') {

				this.appMenuModel.items =
					this.appMenuModel.items.concat.apply(this.appMenuModel.items,
														 this.wordItems);
			}
			else if (this.document_type == 'ppt') {
				this.appMenuModel.items =
					this.appMenuModel.items.concat.apply(this.appMenuModel.items,
														 this.powerpointItems);
			}

			this.appMenuModel.items = this.appMenuModel.items.concat.apply(
				this.appMenuModel.items, this.menuBottomItems);

			var appAttrs = { omitDefaultItems: true };

			this.controller.setupWidget(Mojo.Menu.appMenu,
										appAttrs,
										this.appMenuModel);

			// Setup Find Widget
			var findAttributes = {
								   findFieldName: 'find_it',
								   handleClear: true,
								   handleEnter: true,
								   showOnKey: true,
								   widgetTop: '0px'
								 };

			this.controller.setupWidget('findField', findAttributes, null);

			// Setup Spinner Widget
			this.spinnerAttributes = {
									   property: 'p',
									   spinnerSize: Mojo.Widget.spinnerSmall
									 };

			this.spinnerModel = { p: false };

			this.controller.setupWidget(this.spinner_id,
										this.spinnerAttributes,
										this.spinnerModel);

			// This is the widget for the Save As scene
			this.saveAttributes = {
									modelProperty: 'original',
									autoResize: false,
									multiline: false,
									enterSubmits: false,
									limitResize: false,
									disabledProperty: 'p',
									focusMode: Mojo.Widget.focusSelectMode
								  };

			this.saveModel = { p: false, 'original' : '' };

			this.controller.setupWidget('text_field', this.saveAttributes, this.saveModel);

			this.findField = this.controller.get('findField');
			this.findField.addEventListener('mojo-find-clear', this.handleFindClear.bindAsEventListener(this), false);
			this.findField.addEventListener('mojo-find-go', this.handleFindGo.bindAsEventListener(this), false);
			this.findField.addEventListener('mojo-find-prev', this.handleFindPrev.bindAsEventListener(this), false);
			this.findField.addEventListener('mojo-find-next', this.handleFindNext.bindAsEventListener(this), false);

			this.controller.document.addEventListener(Mojo.Event.activate,
					this._handleFocus, false);

			this.controller.document.addEventListener(Mojo.Event.deactivate,
					this._handleFocus, false);

			if (findAttributes.showOnKey) {
				this.controller.listen(this.controller.sceneElement, Mojo.Event.keydown,
						this.handleKeyDown.bindAsEventListener(this));
			}

			this.controller.setupWidget('loading-doc-spinner', {spinnerSize:Mojo.Widget.spinnerLarge});
			this._loadingScrim = this.controller.get('loading-doc');
			this._loadingSpinner = this.controller.get('loading-doc-spinner');
			
			// this.headerSpacer = this.controller.get('header-spacer');
			// this.headerSpacer.hide();
			this.controller.listen('scrim',Mojo.Event.tap, this.propertiesDialogHide.bindAsEventListener(this));
			this.docInfo = this.controller.get('doc-info');
			this.docInfo.hide();
			this.docInfoText = this.controller.get('doc-info-text');
			this.controller.setupWidget("doc-info-text-scroller",  { mode: 'vertical' }, {});
			
			//this.menuPanel = this.controller.get('menu-panel-container');
			this.docInfoText.setStyle({height:0});
			Mojo.Log.info("Setup complete");
		}
		catch (e) {
			Mojo.Log.logException(e, 'setup');
		}
    },

    activate: function(param) {
        Mojo.Log.info("DocumentAssistant: activate: '%s'", Object.toJSON(param));
		this.controller.get('mainDisplay').show();
		this.sceneActive = true;
        this.findField.mojo.focus();
    },

    ready: function() {
		try {
			Mojo.Log.info("DocumentAssistant: ready.");

			this._hideLoadingSpinner();
			this._loadingSpinnerTimeout = this.controller.window.setTimeout(this._showLoadingSpinner, 2000);
			this.controller.listen(this.controller.get('head-title-td'), 'click', this.showDocumentProperties);
			this.controller.listen(this.controller.get('head-spin-td'), 'click', this.showDocumentProperties);

			// Set the view menu's spacer to be always 0 by calling a show.
			this.showHideView(true);

			Mojo.Log.info("DocumentAssistant: ready is done.");
		}
		catch (e) {
			Mojo.Log.logException(e, 'ready');
		}
    },

    cleanup: function() {
        Mojo.Log.info("DocumentAssistant: cleanup");
    },

    deactivate: function() {
        Mojo.Log.info("DocumentAssistant: deactivate");
		this.sceneActive = false;
        this.findField.mojo.blur();
    },

	_hideLoadingSpinner: function() {
		this._loadingSpinnerTimeout = null;
		this._loadingSpinner.mojo.stop();
		this._loadingScrim.hide();
	},

	_showLoadingSpinner: function(loading) {
		this._loadingSpinnerTimeout = null;
		this._loadingSpinner.mojo.start();
		this._loadingScrim.show();
		var now = new Date();
		this._spinnerShowTime = now.getTime();
	},

    _handleFocus: function(event) {
        Mojo.Log.info("DocumentAssistant: _handleFocus");

        if (event.type == Mojo.Event.deactivate) {
            this.turnOffPageFoot();
        }
        else {
			this.adapter.focus();
        }
    },

    handleKeyDown: function(event) {
        var keyCode = event.originalEvent.keyCode;

		if (!this.sceneActive) {
			return;
		}

		if ( keyCode == Mojo.Char.metaKey ||
			keyCode == 129)	// Orange key
		{
			return;
		}
		if ( (keyCode != Mojo.Char.ctrl) && 
			 (keyCode != Mojo.Char.opt) && 
			 (keyCode <= Mojo.Char.deleteKey)) 
		{
			return;
		}
		if (keyCode >= 0xE000 && keyCode <= 0xF8FF)
		{
			// E000 ... F8FF is the unicode private use area, and used by the
			// platform (in some instances) as gesture navigation "keys".
			// Regardless, they are *not* valid printable characters.
			return;
		}

		// The modifier key codes are <= 46
        if (!this.saveShowing && !this.propertiesShowing && !this.commentsShowing &&
            !this.findShowing && !this.pageFootEdit && !this.pageHeadEnt &&
            !this.slideShowRunning && this.resizeMode == 'off')
        {
            this.showFind();
        }

		// If the findField does not have the focus, make it have focus
		if (this.findShowing && !this.pageFootEdit)
		{
			this.findField.mojo.focus();
		}

    },

    _handleWindowResize: function(event) {
        Mojo.Log.info("DocumentAssistant: _handleWindowResize %d x %d.",
			this.controller.window.innerWidth, this.controller.window.innerHeight);
    },

    lunatap: function(event) {
        Mojo.Log.info("DocumentAssistant: tap at (%d, %d), count:%d",
				event.down.screenX,event.down.screenY, event.count);

        if (this.docPropRunning) {
            return;
		}

        if (event.count === 1) {
            this.singleClick(event.down.screenX, event.down.screenY);
		}
        else if (event.count === 2) {
            this.doubleClick(event.down.screenX, event.down.screenY);
		}
    },

    mousecheck: function (e) {
		Mojo.Log.info("DocumentAssistant: mousecheck");

		if (this.docPropRunning) {
			return;
		}

		// Make sure we are not in entry mode in the page of page
		this.turnOffPageFoot();
    },

	handleMouseDown: function(e) {
        Mojo.Log.info("DocumentAssistant: handleMouseDown");
		if (this.propertiesShowing) {
			this.openDialog.mojo.close();
		}
    },

    gestureStart: function(e) {
        Mojo.Log.info("DocumentAssistant: gestureStart");

        if (this.docPropRunning) {
            return;
		}

        this.adapter.gestureStart(e.scale, e.rotation);
    },

    gestureChange: function(e) {
        Mojo.Log.info("DocumentAssistant: gestureChange");

        if (this.docPropRunning) {
            return;
		}

        this.adapter.gestureChange(e.scale, e.rotation);
    },

    gestureEnd: function(e) {
        Mojo.Log.info("DocumentAssistant: gestureEnd");

        if (this.docPropRunning) {
            return;
		}

        this.adapter.gestureEnd(e.scale, e.rotation);
    },

    flickcheck: function(event) {
        Mojo.Log.info("DocumentAssistant: flickcheck %d", this.document_id);

        if (this.docPropRunning) {
            return;
		}

        this.mousecheck();

        if (!this.slideShowRunning)
        {
            this.controller.serviceRequest( 'palm://com.palm.office/events/handleFlick',
                {
                    parameters: {
                                  docid: this.document_id,
                                  xCoord: event.velocity.x,
                                  yCoord: event.velocity.y
                                },

                    onSuccess: function(payload) 
					{
                        Mojo.Log.info("handleFlick payload = '%s'", payload);

                        if (this.document_type == 'ppt') {
                            this.updatePageFootOf();
						}
                    }.bind(this),

                    onFailure: function(payload) {
						Mojo.Log.error("handleFlick failed: " + Object.toJSON( payload ) );
                    }
                });
        }

		// This prevents a tap event when doing a flick
		event.stop();
    },

    handleCommand: function(event) {
        Mojo.Log.info("DocumentAssistant: handleCommand: type='%s', command='%s'",
				event.type, event.command);

        if (event.type == Mojo.Event.commandEnable) {
            if (event.command == Mojo.Menu.helpCmd) {
                event.stopPropagation();
			}
        }

        if (event.type == Mojo.Event.back) {
            if (this.slideShowRunning) {
                event.stop();
                this.fileAssistant.stopSlideShow();
            }
            else {
                this.controller.stageController.swapScene('recent');
            }
        }

        if (event.type == Mojo.Event.command)
        {
			var request;
            if (!this.saveShowing && !this.propertiesShowing &&
                !this.commentsShowing && !this.findShowing) {

                try {
                    Mojo.Log.info("Got command: '%s'", event.command);

                    switch (event.command)
                    {
						case 'cmd-menu-tap':
							break;

                        case 'file-open-cmd':
                            this.openFilePicker();
                            break;

                        case 'file-saveas-cmd':
                            this.saveAsDialog();
                            break;

                        case 'share-cmd':
                            this.shareDocument();
                            break;

                        case 'find-cmd':
                            if (!this.slideShowRunning && this.resizeMode == 'off') {
                                this.showFind();
							}

                            break;

                        case 'widemode-cmd':
                            this.fileAssistant.toggleWideMode();
                            break;

                        case 'ppt-notes':
                            if (this.slideShowRunning) {
                                this.fileAssistant.stopSlideShow();
							}

                            this.notesShowing = !this.notesShowing;
                            this.fileAssistant.doNotes();

                            break;

                        case 'ppt-outline':
                            if (this.slideShowRunning) {
                                this.fileAssistant.stopSlideShow();
							}

                            this.fileAssistant.showPPTOutline();

                            break;

                        case 'ppt-pageof':
                            this.fileAssistant.showSlideText();
                            break;

                        case 'ppt-play':
                            this.showHideView(false);
                            this.showHideCmd(false);

							if (this.slideShowRunning) {
                                this.fileAssistant.stopSlideShow();
							}
							else {
								this.fileAssistant.startSlideShow();
							}
                            break;

                        case 'xls-outline':
                        case 'xls-pageof':
                            this.fileAssistant.showXLSOutline(true);
                            break;
							
						case 'prev-cmd':
							if (this.getCurrentPage() >= 1) {
								this.fileAssistant.gotoPage(this.getCurrentPage() - 1);
							}
							break;
							
						case 'next-cmd':
							if (this.getCurrentPage() < this.getPageCount() - 1) {
								this.fileAssistant.gotoPage(this.getCurrentPage() + 1);
							}
							break;
							
						case 'edit-cmd':
							this.showFootPageOf();
							break;

                        case 'resize-cmd':
                            this.resizeCmd();
                            break;

                        case 'xls-showall-cmd':
                            this.controller.serviceRequest( 'palm://com.palm.office/excel/unhideAll',
								{
									parameters: { docid: this.document_id },

									onSuccess: function(payload) {
									},

									onFailure: function(payload) {
										Mojo.Log.error("unhideAll failed: " + Object.toJSON( payload ) );
									}
								});
                            break;

                        case Mojo.Menu.helpCmd:
                            Mojo.Log.info("Help command for docviewer");

                            this.controller.serviceRequest('palm://com.palm.applicationManager', {
								method: 'open',
								parameters: {
									id: 'com.palm.app.help',
									params: {
										target: "http://help.palm.com/doc_view/index.html"
									}
								} 
							});

                            break;

                        case 'upgrade-cmd':
                            var args = {
                                         name: 'upgrade',
                                         disableSceneScroller: true
                                       };

                            this.controller.stageController.pushScene(args, this);
                            break;
                    }
                }
                catch (e)
                {
                    Mojo.Log.logException(e);
                }
            }
            else
            {
                if (event.command == 'find-cmd' && this.findShowing) {
                    this.hideFind();
				}
            }
        }
    },

    findIndex: function(model, what) {
        Mojo.Log.info("DocumentAssistant: findIndex");

        var index = -1;

        for (var i = 0; i < model.items.length; i++)
        {
            if (model.items[i].command == what)
            {
                index = i;
                break;
            }
        }

        return index;
    },

    changeItems: function(what) {
        Mojo.Log.info("DocumentAssistant: changeItems what = '%s'", what);

        var index = undefined;

        switch (what)
        {
            case 'ppt-outline':
                break;

            case 'ppt-play':
                break;

            case 'ppt-pageof':
                break;

            case 'ppt-play':
                break;

            case 'xls-pageof':
            case 'xls-outline':
                break;
        }

        if (this.cmdMenuModel !== undefined) {
            this.controller.modelChanged(this.cmdMenuModel);
		}
    },

	animateView: function(visible,callback) {
		//visible?this.headerTemplate.show():this.headerTemplate.hide();
		var header = this.controller.get('topHead');
		Mojo.Animation.animateStyle(header, 'top', 'bezier', {
					from: -50,
					to: 0,
					duration: 0.5,
					curve:'over-easy',
					reverse:!visible,
					onComplete: callback
		});
	},
	
	animateMenuPanelHide: function(visible){
		if (visible) {
			this.docInfo.show();
		}
		var docInfoHide = function() {
			this.docInfo.hide();
		};
		Mojo.Animation.animateStyle(this.docInfoText, 'height', 'bezier', {
					from: 10,
					to: 270,
					duration: 0.5,
					curve:'over-easy',
					reverse:!visible,
					onComplete: visible?undefined:docInfoHide.bind(this)
					}
		);
	},

    showHideView: function(visible,callback) {
        Mojo.Log.info("DocumentAssistant: showHideView (%s) findShowing=%s", visible, this.findShowing);

        if (!this.findShowing && !this.propertiesDialogShowing) {
			// Do NOT animate the menu spacer away because we've disabled it for
			// for our needs
			var menuAssistant = this.controller._menu.assistant;
			menuAssistant.viewSpacerHeight = 0;
			this.animateView(visible,callback);

			
			//visible?this.headerSpacer.show():this.headerSpacer.hide();

            if (visible && !this.viewMenuVisible) {
                if (this.document_type === 'ppt' && this.notesShowing) {
                    this.controller.get('noteScroll').style.height = this.pptScrollTop + 'px';
				}

                this.viewMenuVisible = true;
            }
            else if (!visible && this.viewMenuVisible) {
                if (this.document_type === 'ppt' && this.notesShowing) {
                    this.controller.get('noteScroll').style.height = this.pptScrollTop + this.pptSize +'px';
				}

                this.viewMenuVisible = false;
            }
        }
    },

    showHideCmd: function(visible) {
        Mojo.Log.info("DocumentAssistant: showHideCmd (%d)", visible);

        if (this.cmdMenuModel !== undefined) {
            if (!this.findShowing) {
                this.controller.setMenuVisible(Mojo.Menu.commandMenu, visible);
            }
        }
    },

    propertiesDialog: function(propertiesText) {
        Mojo.Log.info("DocumentAssistant: propertiesDialog");
		this.propertiesDialogShowing = true;
        this.stopSpinner();

        // this.controller.showDialog({
        //     template: 'document/properties-dialog',
        //     assistant: new PropertiesDialogAssistant(this),
        //     content: propertiesText
        // });
		//console.log(propertiesText);
		this.docInfoText.innerHTML = propertiesText;

		this.animateMenuPanelHide(true);

        // This is called to re-evaluate the scroller.  It causes the little down arrow
        // to be displayed if previously, there was no content in the scroller (and thus no arrow).
        this.controller.get("doc-info-text-scroller").mojo.validateScrollPosition();
    },

	propertiesDialogHide: function() {
		Mojo.Log.info("propertiesDialogHide: closing");
		this.propertiesDialogShowing = false;
		//this.showHideView(true);
        //this.showHideCmd(true);
        this.animateMenuPanelHide(false);
    },

	/**
	 * Used to display a file comment (for any supported file type).
	 */
    optionsDialog: function() {
        Mojo.Log.info("DocumentAssistant: optionsDialog");

        this.controller.showDialog({
            template: 'document/options-dialog',
            assistant: new OptionsDialogAssistant(this)
        });
    },

    saveAsDialog: function() {
        Mojo.Log.info("DocumentAssistant: saveAsDialog");

        this.controller.showDialog({
            template: 'document/saveas-dialog',
            assistant: new SaveAsDialogAssistant(this)
        });
    },

	/**
	 * Display a comment dialog for an Excel document. Cell's can have comments
	 * which are usually indicated by a red triangle in the upper-left corner
	 * of a cell. When a user clicks on a comment a dialog is opened displaying
	 * the actual comment.
	 */
    commentsDialog: function(commentText, commentBottom) {
        Mojo.Log.info("DocumentAssistant: commentsDialog");

        this.controller.showDialog({
            template: 'document/comments-dialog',
            assistant: new CommentsDialogAssistant(this, commentText, commentBottom)
        });
    },

    showFind: function() {

        this.showHideView(false);
        this.showHideCmd(true);
		//this.headerSpacer.show();

        this.setMenuCheck('find-cmd', true);

        this.findField.mojo.showFind();
        this.findShowing = true;
    },

    hideFind: function() {
        Mojo.Log.info("DocumentAssistant: hideFind");

        this.setMenuCheck('find-cmd', false);

        if (this.findShowing) {
            this.closeSearch();
		}

        this.findShowing = false;
        //this.controller.get('findField').mojo.hideFind();

        this.showHideView(true, this.findField.mojo.hideFind);
        this.showHideCmd(true);
    },

    handleFind: function(event) {
        Mojo.Log.info("DocumentAssistant: handleFind");

        this.findCancel = false;
        this.newFindString = event.findString;

        Mojo.Log.info("newFindString = '%s'", this.newFindString);
        Mojo.Log.info("findString = '%s'", this.findString);

        if (this.newFindString.length > 0 && this.findString != this.newFindString) {

            if (!this.findString.empty()) {
                this.closeSearch();
			}

            this.findString = event.findString;
            this.resultCount = '0';

            this.submitSearch(this.findString);
        }
    },

    handleFindClear: function(event) {
        Mojo.Log.info("DocumentAssistant: handleFindClear");

        this.hideFind();
    },

    handleFindGo: function(event) {
        Mojo.Log.info("DocumentAssistant: handleFindGo");

        this.newFindString = event.findString;
        this.findCancel = event.cancel;

        Mojo.Log.info("cancel = %d", this.findCancel);
        Mojo.Log.info("newFindString = '%s'", this.newFindString);
        Mojo.Log.info("oldfindString = '%s'", this.findString);

        //this.closeSearch();

        if (this.findCancel) {
            Mojo.Log.info("We need to stop the search...");
            this.closeSearch();
        }
        else {
            if (this.newFindString.length > 0 && this.findString != this.newFindString) {
                if (!this.findString.empty()) {
                    this.closeSearch();
                }

                this.findString = event.findString;
                this.resultCount = '0';

                Mojo.Log.info("Starting the search on: '%s'", this.findString);

                this.submitSearch(this.findString);
            }
            else if (this.findString == this.newFindString)
            {
                Mojo.Log.info("Show the results...");
                this.showResult();
            }
        }
    },

    handleFindPrev: function(event) {
        Mojo.Log.info("DocumentAssistant: handleFindPrev");

        this.previousSearch();
    },

    handleFindNext: function(event) {
        Mojo.Log.info("DocumentAssistant: handleFindNext");

        this.nextSearch();
    },

    showResult: function() {
        Mojo.Log.info("DocumentAssistant: showResult");

        this.findField.mojo.showResult(this.resultCount);
    },

    stopSpinner: function() {
        Mojo.Log.info("DocumentAssistant: stopSpinner");

        this.spinnerRunning = false;
        this.spinnerModel.p = false;
        this.controller.modelChanged(this.spinnerModel);
    },

    startSpinner: function() {
        Mojo.Log.info("DocumentAssistant: startSpinner");

        this.spinnerRunning = true;
        this.spinnerModel.p = true;
        this.controller.modelChanged(this.spinnerModel);
    },

    resizeCmd: function() {
        if (this.resizeMode === 'on') {
            this.resizeMode = 'off';
		}
        else {
            this.resizeMode = 'on';
		}

        this.setMenuCheck('resize-cmd', (this.resizeMode == 'on'));

        this.controller.serviceRequest( 'palm://com.palm.office/excel/resizeMode',
			{
				parameters: {
							  docid: this.document_id,
							  mode: this.resizeMode
							},

				onSuccess: function(payload) {
					Mojo.Log.info("Successfully set resize mode");
				},

				onFailure: function(payload) {
					Mojo.Log.error("resizeMode failed: " + Object.toJSON( payload ) );
				}
			});
    },

    shareDocument: function() {
        Mojo.Log.info("DocumentAssistant: shareDocument");
        Mojo.Log.info("opening e-mail and attaching: '%s'", this.filename);

        this.controller.serviceRequest( 'palm://com.palm.applicationManager',
			{
				method: 'open',

				parameters: {
					id: 'com.palm.app.email',

					params: {
							  attachments: [
								{ fullPath: this.filename, displayName: this.document_name }
							  ]
							}
					}
			});
    },

    setMenuCheck: function(command, checked) {
        Mojo.Log.info("DocumentAssistant: setMenuCheck: command='%s', checked=%d", command, checked);

        var index = this.findIndex(this.appMenuModel, command);

        if (index !== -1) {
            this.appMenuModel.items[index].chosen = checked;
		}
		else {
			Mojo.Log.error("Can't find command");
		}
    },

	HasError: function(error_type) {

		Mojo.Log.warn("Adapter: HasError: %d", error_type);
		this.openRequestComplete = true;
		if (this._loadingSpinnerTimeout) {
			this.controller.window.clearTimeout(this._loadingSpinnerTimeout);
			this._loadingSpinnerTimeout = null;
		}
		this._hideLoadingSpinner();

		switch (parseInt(error_type,10)) {
			case 0:
				Mojo.Log.error("Open Document Error!");

				this.errorText = $L('Opening document failed');
				this.controller.window.setTimeout( this.showError, 250);
				break;

			case 2:
				Mojo.Log.error("Unsupported Encryption Error!");

				this.errorText = $L('Document encryption type not supported');
				this.controller.window.setTimeout( this.showError, 250);
				break;

			case 3:
				Mojo.Log.error("Documentation Encryption Not Supported!");

				this.errorText = $L('Document encryption is not supported');
				this.controller.window.setTimeout( this.showError, 250);
				break;

			default:
				Mojo.Log.error("Not handling this case: '%s'", error_type);
		}
	},

	initializeVars: function(docid) {

		try {

			Mojo.Log.info("Adapter: initializeVars %d", docid);

			this.openRequestComplete = true;
			if (this._loadingSpinnerTimeout) {
				this.controller.window.clearTimeout(this._loadingSpinnerTimeout);
				this._loadingSpinnerTimeout = null;
			}
			var now = new Date();
			var minSpinnerDisplayTime = 1000;
			var remainingShowTime = this._spinnerShowTime + minSpinnerDisplayTime - now.getTime();
			if (remainingShowTime > 0) {
				this._loadingSpinnerTimeout = this.controller.window.setTimeout(this._hideLoadingSpinner, remainingShowTime);	
			}
			else {
				this._hideLoadingSpinner();
			}

			this.document_id = docid;

			if (!this.initDone) {

				this.initDone = true;

				this.fileAssistant.docLoaded();

				this.controller.get('documentname').innerHTML = this.document_noext;
			}
		}
		catch (e) {
			Mojo.Log.logException(e, "initializeVars");
		}
	},

	/**
	 * Find out what resource was selected and open it.
	 */
	openResource: function(docId) {
		this.controller.serviceRequest( 'palm://com.palm.office/common/getMimeInfo',
				{
					parameters: { docid: docId },

					onSuccess: function(payload) {
						if ((payload.errorCode !== undefined) || (payload.target !== true)) {
							Mojo.Log.error("getMimeInfo failed: " + Object.toJSON( payload ) );
							return;
						}
						Mojo.Log.info("Mime payload: %s", payload.target);

						var targetString = payload.target;

						if (targetString.substr(0,7) == 'http://')
						{
							var openParams = {
											   scene: 'page',
											   target: payload.target
											 };

							this.controller.serviceRequest( 'palm://com.palm.applicationManager',
								{
								  method: 'open',
								  parameters: {
												id: 'com.palm.app.browser',
												params: openParams
											  }
								});
						}
						else
						{
							this.controller.serviceRequest( 'palm://com.palm.applicationManager/open',
								{
									parameters: payload,

									onSuccess: function(payload) {
									},

									onFailure: function(payload) {
										Mojo.Log.error("open failed!");
									}
								});
						}
					}.bind(this),

					onFailure: function(payload) 
					{
						Mojo.Log.error("getMimeInfo failed: " + Object.toJSON( payload ) );
					}
				});
	},

	ActionRequest: function(command, data) {

		Mojo.Log.info("Adapter: ActionRequest (%d, %s)", command, data);

		// these all come from DocAdapterMessages.h
		var MsgResourceLinkClick = 1;
		var MsgCommentLinkClick = 2;
		var MsgIdleClick = 3;
		var MsgSelectColumn = 4;
		var MsgMultiSelect = 5;
		var MsgExitResizeMode = 6;
		var MsgChangePageNum = 7;

		switch(command) {

			case MsgResourceLinkClick:
				Mojo.Log.info("Clicked on resource.");
				this.openResource(this.document_id);
				break;

			case MsgCommentLinkClick:
				Mojo.Log.info("Clicked on comment.");
				this.fileAssistant.getComment();
				break;

			case MsgIdleClick:
				Mojo.Log.info("Idle click.");
				//this.controller.window.setTimeout( this.showMenuBars, 1000);
				break;

			case MsgSelectColumn:
				Mojo.Log.info("Selected a column.");
				this.fileAssistant.showPopupMenu();
				break;

			case MsgMultiSelect:
				Mojo.Log.info("Selected multiple rows/columns.");
				this.fileAssistant.showPopupMultiMenu();
				break;

			case MsgExitResizeMode:
				Mojo.Log.info("Exit resize mode.");
				this.resizeCmd();
				break;

			case MsgChangePageNum:
				Mojo.Log.info("Changed page no.");
				this.setCurrentPage(parseInt(data,10));
				if (this.document_type === 'ppt' || this.document_type === 'xls') {
					this.updatePageFootOf();
				}
				break;

			default:
				Mojo.Log.error("Not handled: (%d, %s)", command, data);
				break;
		}
	},

	setPageCount: function(count) {
		this.pageCount = count;
	},
	
	getPageCount: function() {
		return this.pageCount;
	},

	setCurrentPage: function(page) {
		this.cur_page = page;
	},
	
	getCurrentPage: function() {
		return this.cur_page;
	},

	// TODO Called from a timeout to possibly fix a race condition????
	showError: function() {

		Mojo.Log.info("showError()");

		this.controller.stageController.pushScene('error', this);
	},

	InstallOfficeAdapter: function(replacement) {

		Mojo.Log.info("Entering InstallOfficeAdapter()");

		var headerHeight = parseInt(this.controller.get('header').getStyle('height'), 10);

		Mojo.Log.info("@@@ headerHeight = ", headerHeight);

        var obj = this.controller.document.createElement('object');
		obj.setAttribute('type', 'application/x-palm-officeadapter');

		var width = this.controller.window.innerWidth;
		var height = this.controller.window.innerHeight - headerHeight;

		obj.setAttribute('width', width);
		obj.setAttribute('height', height);

		obj.setAttribute('file', this.filename);
		obj.setAttribute('x-palm-pass-event', true);

		this.document_type = this.appAssistant.GetFileExtension(this.filename);
		if (this.document_type === 'txt') {
			this.wasTextDoc = true;
			this.document_type = 'doc';
		}

		replacement.parentNode.replaceChild(obj, replacement);
		var splittext = this.filename.split('/');
		this.document_name = splittext[splittext.length-1];

		if (this.wasTextDoc) {
			this.document_noext = this.document_name.substr(0, this.document_name.indexOf('.txt'));
		}
		else {
			this.document_noext = this.document_name.substr(0, this.document_name.indexOf('.'+this.document_type));
		}

		obj.eventListener = this;

		return obj;
	},

	showDocumentProperties: function()
	{
		Mojo.Log.info("showDocumentProperties");
		if(this.propertiesDialogShowing){
			Mojo.Log.info("showDocumentProperties closing");
			this.propertiesDialogHide();
			return false;
		}

		this.showHideView(true);
		this.showHideCmd(true);
		if (this.propertiesText === undefined)
		{
			this.docPropRunning = true;
			this.startSpinner();
			this.controller.serviceRequest( 'palm://com.palm.office/common/getDocProperties',
				{
					parameters: { docid: this.document_id },

					onSuccess: function(payload) 
					{
						Mojo.Log.info("payload = '%s'", payload);
						
						//var old_date = convertDate(payload.lastsave);
						//var new_date = lastMod(old_date);

						if (payload.errorCode !== undefined || 
							payload.author === undefined ||
							payload.description === undefined ||
							payload.name === undefined ||
							payload.createdate === undefined ||
							payload.lastsave === undefined) {

							Mojo.Log.error("getDocProperties failed to get properties: " + Object.toJSON( payload ) );
							return;
						}
						var lastsave = new Date(this.convertDate(payload.lastsave));
						var createdate = new Date(this.convertDate(payload.createdate));

						var save_dt = Mojo.Format.formatDate( lastsave, { date: 'medium', time: 'short' } );
						var create_dt = Mojo.Format.formatDate( createdate, { date: 'medium', time: 'short' } );

						this.propertiesText = '';

						if (payload.description.length === 0)
						{
							payload.description = $L("(no description)");
						}

						var template = new Template($L('<div class="palm-body-text">Name: #{document_name}</div>'));
						if (payload.name.length === 0) {
							this.propertiesText+=template.evaluate({document_name: this.document_name});
						}
						else {
							this.propertiesText+=template.evaluate({document_name: payload.name});
						}
						template = new Template($L('<div class="palm-body-text">Author: #{author}</div>'));
						this.propertiesText+=template.evaluate({author: payload.author});
						template = new Template($L('<div class="palm-body-text">Description: #{description}</div>'));
						this.propertiesText+=template.evaluate({description: payload.description});
						template = new Template($L('<div class="palm-body-text">Last Saved Date: #{savedate}</div>'));
						this.propertiesText+=template.evaluate({savedate: save_dt});
						template = new Template($L('<div class="palm-body-text">Creation Date: #{createdate}</div>'));
						this.propertiesText+=template.evaluate({createdate: create_dt});
						
						if (this.document_type === 'doc') {
							if (payload.wordcnt !== undefined) {
								template = new Template($L('<div class="palm-body-text">Word count: #{wordcnt}</div>'));
								var wordCount = Mojo.Format.formatNumber( Number(payload.wordcnt) );
								this.propertiesText+=template.evaluate({wordcnt: wordCount});
							}
						}
						else if (this.document_type == 'ppt') {
							template = new Template($L('<div class="palm-body-text">Sheet count: #{slide_cnt}</div>'));
							this.propertiesText+=template.evaluate({slide_cnt: this.getPageCount()});
						}

						this.docPropRunning = false;

						this.propertiesDialog(this.propertiesText);
						
					}.bind(this),
					
					onFailure: function(payload) {
						Mojo.Log.error("getDocProperties failed: %s", Object.toJSON( payload ) );
					}
				});
		}
		else {
			
			this.propertiesDialog(this.propertiesText);
		}
	},


	showDocumentOptions: function()
	{
		Mojo.Log.info("showDocumentOptions");

		this.showHideView(true);
		this.showHideCmd(true);
		this.optionsDialog();
	},


	openFilePicker: function()
	{
		this.doCancel();

		this.controller.serviceRequest('palm://com.palm.applicationManager', {
			method: 'open',
			parameters: { 'id': 'com.palm.app.docviewer' }
		});
	},


	saveMRU: function(listempty)
	{
		if (this.doMRU) {
			if (!listempty && this.mruArray.length === 0) {
				this.getMRU();
				this.doSaveMRU = true;
				return;
			}

			Mojo.Log.info("saveMRU: filename = '%s'", this.filename);

			// Remove the element if it exists in the list already
			var index_found = this.mruArray.indexOf(this.filename);

			Mojo.Log.info("index_found = '%s'", index_found);

			if (index_found !== -1) {
				this.mruArray.splice(index_found, 1);
			}

			this.mruArray.unshift(this.filename);

			Mojo.Log.info("this.mruArray = '%s'", this.mruArray);
			Mojo.Log.info("filename = '%s'", this.filename);

			// Only add files to the MRU if they are in /media/internal/
			if (this.filename.indexOf('/media/internal/') !== -1) {
				this.resetMRU();
			}
		}
	},


	getMRU: function()
	{
		this.controller.serviceRequest( 'palm://com.palm.preferences/appProperties/Get',
			{
				parameters: {
							  appId:'com.palm.app.docviewer',
							  key:'recent'
							},

				onSuccess: function(payload) {
					var val = payload.recent;

					if (val !== undefined) {
						for (var i = 0; i < val.length && i < 10; i++) {
							this.mruArray.push(val[i]);
						}
					}

					if (this.doSaveMRU) {
						this.saveMRU(true);
					}

					this.doSaveMRU = false;
				}.bind(this),

				onFailure: function(payload) {
					Mojo.Log.error("appProperties/Get failed!");
				}
			});
	},


	resetMRU: function()
	{
		this.controller.serviceRequest( 'palm://com.palm.preferences/appProperties/Set',
			{
				parameters: {
							  appId: 'com.palm.app.docviewer',
							  key: 'recent',
							  value: this.mruArray.slice(0, 19)
							},

				onSuccess: function(payload) {
					Mojo.Log.info("appProperties/Set: onSuccess");
				},

				onFailure: function(payload) {
					Mojo.Log.error("appProperties/Set failed!");
				}
			});
	},


	doCancel: function()
	{
		this.showHideView(true);
		this.showHideCmd(true);
	},


	doAutoHide: function()
	{
		if (this.document_type != 'xls') {

			this.isHidden = true;

			this.showHideView(false);
			this.showHideCmd(false);
			this.controller.window.clearTimeout(this.autoHideTimeout);
		}
	},


	showMenuBars: function()
	{
		if (this.isHidden) {
			this.isHidden = false;

			this.showHideView(true);
			this.showHideCmd(true);
		}
		else {
			this.doAutoHide();
		}
	},

	showElement: function(element)
	{
		this.controller.get(element).style.visibility = 'visible';
	},


	hideElement: function(element)
	{
		this.controller.get(element).style.visibility = 'hidden';
	},


	previousSearch: function()
	{
		this.controller.serviceRequest( 'palm://com.palm.office/common/previousResult',
			{
				parameters: { docid: this.document_id },

				onSuccess: function(payload) {
					if (payload.errorCode !== undefined || payload.returnValue !== true) {
						Mojo.Log.error("previousResult failed: " + Object.toJSON( payload ) );
						return;
					}

				   Mojo.Log.info("success on previous search");
				   this.adapter.invalidateScreen();
				}.bind(this),

				onFailure: function(payload) {
					Mojo.Log.error("previousResult failed: " + Object.toJSON( payload ) );
				}
			});
	},


	nextSearch: function() {

		this.controller.serviceRequest( 'palm://com.palm.office/common/nextResult',
			{
				parameters: { docid: this.document_id },

				onSuccess: function(payload) 
				{
					if (payload.errorCode !== undefined || payload.returnValue !== true) {
						Mojo.Log.error("nextResult failed: " + Object.toJSON( payload ) );
						return;
					}
					this.adapter.invalidateScreen();
				}.bind(this),

				onFailure: function(payload) 
				{
					Mojo.Log.error("nextResult failed: " + Object.toJSON( payload ) );
				}
			});
	},


	submitSearch: function(value) {

		Mojo.Log.info("Searching for '%s'", value);

		this.controller.serviceRequest( 'palm://com.palm.office/common/Search',
			{
				parameters: { docid: this.document_id, search: value },

				onSuccess: function(payload) {

					if (payload.errorCode !== undefined || payload.resultcount === undefined) {
						Mojo.Log.error("Search failed get resultcount: " + Object.toJSON( payload ) );
						return;
					}
					Mojo.Log.info("Search completed count = '%s'", payload.resultcount);

					this.resultCount = payload.resultcount;
					this.showResult();
					//this.adapter.invalidateScreen();
				}.bind(this),

				onFailure: function(payload) {
					Mojo.Log.error("Search failed: " + Object.toJSON( payload ) );
				}
			});
	},


	closeSearch: function() {

		Mojo.Log.info("Closing Search");

		this.findString = '';
		this.newFindString = '';

		this.controller.serviceRequest( 'palm://com.palm.office/common/closeSearch',
			{
				parameters: { docid: this.document_id },

				onSuccess: function(payload) 
				{
					if (payload.errorCode !== undefined || payload.returnValue !== true) {
						Mojo.Log.error("closeSearch failed: " + Object.toJSON( payload ) );
						return;
					}
					Mojo.Log.info("Search Closed Success!!!");
				},

				onFailure: function(payload) {
					Mojo.Log.error("Search failed: " + Object.toJSON( payload ) );
				}
			});
	},


	saveAs: function(input) {

		Mojo.Log.info("saveAs input = '%s'", input);

		// Not going to allow quotes or semi-colons at this time
		var save_input = input.replace(/"/g, '').replace(/;/g, '').replace(/\//g, '');

		Mojo.Log.info("saveAs input = '%s'", save_input);

		if (save_input !== undefined && save_input.length > 0) {
			var isTextDoc = false;

			var file = save_input.split('.');

			var type = file[file.length-1];

			// Make sure we have the correct extension
			if (this.document_type == 'doc') {
				if ('txt' == this.appAssistant.GetFileExtension(this.filename) && type != 'txt') {
					isTextDoc = true;
					save_input = save_input + '.txt';
				}
				else if (type == 'txt') {
					isTextDoc = true;
				}
				else if (type != 'doc') {
					save_input = save_input + '.doc';
				}
			}
			else if (this.document_type == 'docx') {
				if (type !== 'docx') {
					save_input = save_input + '.docx';
				}
			}
			else if (this.document_type == 'ppt') {
				if (type !== 'ppt') {
					save_input = save_input + '.ppt';
				}
			}
			else if (this.document_type == 'pptx') {
				if (type !== 'pptx') {
					save_input = save_input + '.pptx';
				}
			}
			else if (this.document_type == 'xls') {
				if (type !== 'xls') {
					save_input = save_input + '.xls';
				}
			}
			else if (this.document_type == 'xlsx') {
				if (type !== 'xlsx') {
					save_input = save_input + '.xlsx';
				}
			}

			// If we have a filename
			if (this.filename !== undefined && this.filename != 'unspecified file') {

				var dir = '/media/internal';

				Mojo.Log.info("dir='%s', save_input='%s'", dir, save_input);

				var new_filename = dir + '/' + save_input;

				if (new_filename != this.filename) {
					try {
						this.adapter.saveAs(this.filename, new_filename);

						// Reset some globals
						this.filename = new_filename;
						this.document_name = save_input;

						if (isTextDoc) {
							this.document_noext = this.document_name.substr(0, this.document_name.indexOf('.txt'));
						}
						else {
							this.document_noext = this.document_name.substr(0, this.document_name.indexOf('.'+this.document_type));
						}

						Mojo.Log.info("filename = '%s'", this.filename);
						Mojo.Log.info("document_name = '%s'", this.document_name);
						Mojo.Log.info("this.document_noext = '%s'", this.document_noext);

						this.controller.get('documentname').innerHTML = this.document_noext;

						this.saveMRU(false);
					}
					catch(e) {
						Mojo.Log.logException(e);
					}
				}

				this.doCancel();
			}
		}
	},


	singleClick: function(screenX, screenY) {

		Mojo.Log.info("singleClick at (%d, %d), msgDivPos=%d, viewMenuVisible=%s",
				screenX, screenY, this.msgDivPos, this.viewMenuVisible);

		if (this.viewMenuVisible) {
			screenY -= this.msgDivPos;
		}

		Mojo.Log.info("screenY = '%d'", screenY);

		this.lastScreenClickX = screenX;
		this.lastScreenClickY = screenY;

		if (this.slideShowRunning) {
			if (this.getCurrentPage() == this.getPageCount() - 1) {
				this.fileAssistant.stopSlideShow();
			}
			else {
				this.fileAssistant.nextSlide();
			}

			return;
		}

		// If find is showing then we have to get rid of it
		if (this.findShowing) {
			this.hideFind();
		}
		else {
			this.controller.serviceRequest( 'palm://com.palm.office/events/handleClick',
				{
					parameters: {
								  docid: this.document_id,
								  xCoord: screenX,
								  yCoord: screenY
								},

					onSuccess: function(payload) {
						Mojo.Log.info("handleClick payload = '%s'", payload);
					},

					onFailure: function(payload) {
						Mojo.Log.error("handleClick failed: %s", Object.toJSON( payload ) );
					}
				});
		}
	},


	doubleClick: function(screenX, screenY) {

		Mojo.Log.info('doubleClick');

		var headerHeight = parseInt(this.controller.get('header').getStyle('height'), 10);
		var adapterDownY = screenY - headerHeight; 

		// Only allow double click if we are not in ppt slide show
		if (!this.slideShowRunning)
		{
			this.controller.serviceRequest( 'palm://com.palm.office/events/handleDoubleClick',
				{
					parameters: {
								  docid: this.document_id,
								  xCoord: screenX,
								  yCoord: adapterDownY 
								},

					onSuccess: function(payload) {
						Mojo.Log.info("handleDoubleClick payload = '%s'", payload);
					},

					onFailure: function(payload) {
						Mojo.Log.error("handleDoubleClick failed: " + Object.toJSON( payload ) );
					}
				});
		}
	},


	lastMod: function(the_date) {

		var tmp_date = new Date(the_date);

		var modified = new Date(tmp_date.toGMTString());

		var year = this.whatYear(modified);
		var month = modified.getMonth();
		var day = modified.getDate();
		var hours = modified.getHours();
		var mins = modified.getMinutes();
		var outputTemplate = undefined;
		var ampm = $L('am');

		if (hours === 0) {
			hours = 12;
		}
		else if (hours > 12) {
			hours = hours - 12;
			ampm = $L('pm');
		}

		var last = Date.UTC(year, month, day, 0, 0, 0) / 86400000;

		tmp_date = new Date();

		var today = new Date(tmp_date.toGMTString());

		var year2 = this.whatYear(today);
		var month2 = today.getMonth();
		var day2 = today.getDate();

		var now = Date.UTC(year2, month2, day2, 0, 0, 0) / 86400000;

		var daysago = now - last;

		if (daysago < 0) {
			return '';
		}

		var unit = $L('days');

		if (daysago > 730)
		{
			daysago = Math.floor(daysago / 365);
			outputTemplate = new Template($L('#{daysago} years ago'));
		}
		else if (daysago > 60)
		{
			daysago = Math.floor(daysago / 30);
			outputTemplate = new Template($L('#{daysago} months ago'));
		}
		else if (daysago > 14)
		{
			daysago = Math.floor(daysago / 7);
			outputTemplate = new Template($L('#{daysago} weeks ago'));
		}
		else if (daysago > 1)
		{
			outputTemplate = new Template($L('#{daysago} days ago'));
		}

		var output = '';

		var todayTemplate = new Template($L('Today at #{hours}:#{mins} #{ampm}'));
		var yesterdayTemplate = new Template($L('Yesterday at #{hours}:#{mins} #{ampm}'));
		if (daysago === 0) {
			output = todayTemplate.evaluate({hours: hours, mins: mins, ampm: ampm});
		}
		else if (daysago === 1) {
			output = yesterdayTemplate.evaluate({hours: hours, mins: mins, ampm: ampm});
		}
		else {
			output = outputTemplate.evaluate({daysago: daysago, unit: unit});
		}

		Mojo.Log.info("output = '%s'", output);

		return output;
	},


	whatYear: function(the_date) {

		Mojo.Log.info("whatYear: the_date = '%s'", the_date);

		var input_year = the_date.getYear();

		var output_year = input_year % 100;

		output_year += (output_year < 38) ? 2000 : 1900;

		return output_year;
	},


	convertDate: function(the_date) {

		Mojo.Log.info("convertDate: the_date = '%s'", the_date);

		var new_date = undefined;

		var time_ind = the_date.lastIndexOf(' ');

		var my_date = the_date.substr(0, time_ind);
		var my_time = the_date.substr(time_ind+1);
		var ampm = $L('am');

		var denom = my_time.indexOf($L('am'));

		if (denom == -1) {
			ampm = $L('pm');
		}

		var time = my_time.split(':');

		var hours = time[0];
		var mins = time[1].substr(0, 2);

		if (ampm == $L('pm')) {
			hours = parseInt(hours,10) + 12;
		}

		if (hours >= 24) {
			hours = 0;
		}

		new_date = my_date + ' ' + hours + ':' + mins;

		Mojo.Log.info("new_date = '%s'", new_date);

		return new_date;
	},

	/*********************************************************
	**              FOOTER PAGE OF PAGE FUNCTIONS           **
	**********************************************************/
	turnOffPageFoot: function() {

		if (this.pageFootEdit)
		{
			this.forceFootChange();

			this.pageFootEdit = false;

			this.updatePageFootOf();
			
			this.controller.get('command_pill').removeClassName('palm-depressed');

			this.controller.get('page_foot_ent').hide();
			this.controller.get('page_foot').show();
		}
	},


	updatePageFootOf: function() {

		var page = this.getCurrentPage();
		var total_page = this.getPageCount();

		if (page !== undefined)	{
			
			page++;
			
			var page_len = (total_page+'').length;
			
			this.cmdMenuModel.items[1].items[1].width = 60 + (page_len * 15);			
			this.cmdMenuModel.items[1].items[0].disabled = (page == 1);
			this.cmdMenuModel.items[1].items[2].disabled = (total_page == page);
			this.controller.modelChanged(this.cmdMenuModel);
			
			this.controller.listen(this.controller.get('page_foot_cur_ent'), 'keydown', this.handleFootPage);

			this.controller.get('page_foot_cur').innerHTML = page;
			this.controller.get('page_foot_cnt').innerHTML = total_page;
			
			this.controller.setMenuVisible(Mojo.Menu.commandMenu, true);
		}
	},


	updatePageFootOfEntry: function() {
		
		var page = undefined;
		var total_page = undefined;
		var page_len = '0';

		page = this.getCurrentPage();
		total_page = this.getPageCount();

		if (page !== undefined)
		{
			page++;

			page_len = total_page + '';

			this.controller.get('page_foot_cur_ent').value = page;
			this.controller.get('page_foot_cnt_ent').innerHTML = total_page;
			this.controller.get('page_foot_cur_ent').size = page_len.length;
			this.controller.get('page_foot_cur_ent').maxLength = page_len.length;
			this.controller.get('page_foot_cur_ent').focus();
			this.controller.get('page_foot_cur_ent').select();
		}

		return page_len.length;
	},


	showFootPageOf: function() {

		Mojo.Log.info("showFootPageOf");

		if (!this.pageFootEdit)
		{
			this.showHideView(true);

			this.pageFootEdit = true;

			this.controller.get('command_pill').addClassName('palm-depressed');

			this.controller.get('page_foot').hide();
			this.controller.get('page_foot_ent').show();
			this.controller.get('page_foot_cur_ent').setAttribute(Mojo.Gesture.consumesEnterAttribute, "true");

			this.updatePageFootOfEntry();
		}
		else
		{
			this.showHideView(true);
			this.turnOffPageFoot();
		}
	},


	handleFootPage: function(e) {
		
		if (e.keyCode == Mojo.Char.enter) {
			
			this.forceFootChange();			

			this.showFootPageOf();
		}
		else {
			var c = String.fromCharCode(e.keyCode).toLowerCase();
			var numeric = this.numericMap[c];
			if (numeric) {
				var input = this.controller.get('page_foot_cur_ent');
				if (input.selectionStart !== input.selectionEnd) {
					input.value = numeric;
				}
				else {
					input.value += numeric;
				}				
			}			
			else if (e.keyCode == Mojo.Char.backspace || e.keyCode == Mojo.Char.deleteKey) {
				// fall through
				return;
			}
			this.controller.window.event.returnValue = false;
		}
	},


	forceFootChange: function() {
		
		var goto_page = parseInt(this.controller.get('page_foot_cur_ent').value,10) - 1;

		if (!isNaN(goto_page))
		{
			if (goto_page >= this.getPageCount()) {
				goto_page = this.getPageCount() - 1;
			}
			else if (goto_page < 0) {
				goto_page = 0;
			}

			this.fileAssistant.gotoPage(goto_page);
		}
	}
});




var OptionsDialogAssistant = Class.create({

    initialize: function(sceneAssistant) {
        Mojo.Log.info("OptionsDialogAssistant: initialize");

        this.sceneAssistant = sceneAssistant;
    },

    setup: function(widget) {
        Mojo.Log.info("OptionsDialogAssistant: setup");

        this.sceneAssistant.openDialog = widget;

        this.sceneAssistant.controller.get('open_button').addEventListener(Mojo.Event.tap,
                                          this.handleOpen.bind(this));

        this.sceneAssistant.controller.get('saveas_button').addEventListener(Mojo.Event.tap,
                                            this.handleSaveAs.bind(this));

        this.sceneAssistant.controller.get('cancel_button').addEventListener(Mojo.Event.tap,
                                            this.handleCancel.bind(this));
    },

    activate: function() {
        Mojo.Log.info("OptionsDialogAssistant: activate");
    },

    handleOpen: function() {
        Mojo.Log.info("OptionsDialogAssistant: handleOpen");

        this.sceneAssistant.openDialog.mojo.close();
        this.sceneAssistant.openFilePicker();
    },

	cleanup: function() {
		this.sceneAssistant.openDialog = null;
	},

    handleSaveAs: function() {
        Mojo.Log.info("OptionsDialogAssistant: handleSaveAs");

        this.sceneAssistant.openDialog.mojo.close();

        this.sceneAssistant.saveAsDialog();
    },

    handleCancel: function() {
        Mojo.Log.info("OptionsDialogAssistant: handleCancel");

        this.sceneAssistant.doCancel();
        this.sceneAssistant.openDialog.mojo.close();
    }
});


var SaveAsDialogAssistant = Class.create({

    initialize: function(sceneAssistant) {
        Mojo.Log.info("SaveAsDialogAssistant: initialize");

        this.sceneAssistant = sceneAssistant;
        this.saveModel = this.sceneAssistant.saveModel;
    },

    setup: function(widget) {
        Mojo.Log.info("SaveAsDialogAssistant: setup");

        this.sceneAssistant.openDialog = widget;

        this.sceneAssistant.controller.get('save_button').observe(Mojo.Event.tap,
                                 this.handleSave.bind(this));

        this.sceneAssistant.controller.get('cancel_button').observe(Mojo.Event.tap,
                                   this.handleCancel.bind(this));
    },

    activate: function() {
        Mojo.Log.info("SaveAsDialogAssistant: activate");

        this.sceneAssistant.saveShowing = true;

        this.saveModel.original = this.sceneAssistant.document_noext;
        this.sceneAssistant.controller.modelChanged(this.saveModel, this);
        this.sceneAssistant.controller.get('text_field').mojo.focus();
    },

    deactivate: function() {
        Mojo.Log.info("SaveAsDialogAssistant: deactivate");

        this.sceneAssistant.saveShowing = false;
    },

    cleanup: function() {
        Mojo.Log.info("SaveAsDialogAssistant: cleanup");
		this.sceneAssistant.openDialog = null;
    },

    handleSave: function() {
        Mojo.Log.info("SaveAsDialogAssistant: handleSave");

        var textField = this.sceneAssistant.controller.get('text_field');
        var filename = textField.mojo.getValue();
        if (!filename || (filename.length === 0))
        {
            // If the string is empty, don't do anything - they must cancel or enter a valid string
            // Put the focus back into the text field
            this.sceneAssistant.controller.get('text_field').mojo.focus();
            return;
        }

        this.sceneAssistant.saveAs( filename );
        this.sceneAssistant.openDialog.mojo.close();
    },

    handleCancel: function() {
        Mojo.Log.info("SaveAsDialogAssistant: handleCancel");

        this.sceneAssistant.doCancel();
        this.sceneAssistant.openDialog.mojo.close();
    }
});

/**
 * Used for displaying Excel cell comments.
 */
var CommentsDialogAssistant = Class.create({

    initialize: function(sceneAssistant, commentText, commentBottom) {
        Mojo.Log.info("CommentsDialogAssistant: initialize");

        this.sceneAssistant = sceneAssistant;
		this.commentText = commentText;
		this.commentBottom = commentBottom;
    },

    setup: function(widget) {
        Mojo.Log.info("CommentsDialogAssistant: setup");

        this.sceneAssistant.openDialog = widget;
    },

    activate: function() {
        Mojo.Log.info("CommentsDialogAssistant: activate");

        this.sceneAssistant.commentsShowing = true;

        this.sceneAssistant.controller.get('commentText').innerHTML = this.commentText.stripScripts().stripTags();

        this.sceneAssistant.controller.get('palm-dialog-box').style.width = '300px';
        this.sceneAssistant.controller.get('palm-dialog-box').style.margin = '0px 0px 0px 10px';
        this.sceneAssistant.controller.get('palm-dialog-box').style.top = 'auto';
        this.sceneAssistant.controller.get('palm-dialog-box').style.bottom = this.commentBottom + 'px';

        this.sceneAssistant.controller.get('commentScroll').observe(Mojo.Event.tap, this.handleTap.bind(this));
    },

    deactivate: function() {
        Mojo.Log.info("CommentsDialogAssistant:: deactivate");

        this.sceneAssistant.commentsShowing = false;
    },

    cleanup: function() {
        Mojo.Log.info("CommentsDialogAssistant:: cleanup");
		this.sceneAssistant.openDialog = null;
    },

    handleTap: function() {
        Mojo.Log.info("CommentsDialogAssistant: handleCancel");

        this.sceneAssistant.controller.get('palm-dialog-box').style.top = 'auto';
        this.sceneAssistant.controller.get('palm-dialog-box').style.bottom = 'auto';

        this.sceneAssistant.openDialog.mojo.close();

        this.sceneAssistant.showHideView(true);
        this.sceneAssistant.showHideCmd(true);
    }
});

