//
//  PresentationUIController.js
//  CoverPage
//
//  Created by Richard Anaya on 1/9/2013.
//  Copyright (c) 2014 Evernote. All rights reserved.
//


var PresentationUIController = function(){
    this.objectUrls = [];
    this.stack = [];
    this.captions = [];
    this.resources = {
        PresentClickToExpandImage:"click to expand image",
        PresentClickToReadPDF:"click to read pdf",
        PresentTooltipExitDocViewer:"Exit Document Viewer",
        PresentTooltipExitDocViewerCmd:"ESC",
        PresentTooltipCursorTypes:"Cursor Types",
        PresentTooltipCursorTypesCmd:"Ctrl+P",
        PresentTooltipChangeScreen:"Change Screen",
        PresentTooltipChangeScreenCmd:"Ctrl+S",
        PresentTooltipBlueLaserPointer:"Blue Laser Pointer",
        PresentTooltipBlueLaserPointerCmd:"Ctrl+1",
        PresentTooltipYellowLaserPointer:"Yellow Laser Pointer",
        PresentTooltipYellowLaserPointerCmd:"Ctrl+2",
        PresentTooltipRedLaserPointer:"Red Laser Pointer",
        PresentTooltipRedLaserPointerCmd:"Ctrl+3",
        PresentTooltipArrowPointer:"Arrow Cursor",
        PresentTooltipArrowPointerCmd:"Ctrl+4",
        PresentTooltipFillScreen:"Fill Screen",
        PresentTooltipFillScreenCmd:"Ctrl+0",
        PresentTooltipZoomOut:"Zoom Out",
        PresentTooltipZoomOutCmd:"Ctrl+-",
        PresentTooltipZoomIn:"Zoom In",
        PresentTooltipZoomInCmd:"Ctrl++",
        PresentTooltipActualSize:"Actual Size",
        PresentTooltipActualSizeCmd:"Ctrl+1",
        PresentBackCmd:"Ctrl+[",
        PresentTooltipExitPresMode:"Exit Presentation Mode",
        PresentTooltipExitPresModeCmd:"ESC",
        PresentTooltipActivateNightMode:"Activate Nightmode",
        PresentTooltipDeactivateNightMode:"Deactivate Nightmode",
        PresentTooltipActivateNightModeCmd:"Ctrl+N",
        PresentEndOfNote: "Press &rarr; to go to",
        PresentWaitingLoaderTitle: "Loading {0}",
        PresentFTUEWelcomeFreeSlide1Title: "Welcome to Presentation Mode",
        PresentFTUEWelcomeFreeSlide1Text: "Evernote's Presentation mode lets you share your notes in a full-screen view, without the work of creating slides.",
        PresentFTUEWelcomeFreeSlide2Title: "Illuminate Important Ideas",
        PresentFTUEWelcomeFreeSlide2Text: "Your mouse becomes a laser-pointer so you can show people what to focus on while you present.",
        PresentFTUEWelcomeFreeSlide3Title: "View Documents Without Switching Apps",
        PresentFTUEWelcomeFreeSlide3Text: "Zoom in to images and PDFs to show more detail without switching apps.",
        PresentFTUEWelcomeFreeSlide4Title: "PRESENTATION MODE",
        PresentFTUEWelcomeFreeSlide4Text: "Enjoy this premium feature for a complimentary 30-day period.",
        PresentFTUEWelcomeFreeSlide4StartTrialButton: "Start Trial",
        PresentFTUEWelcomeFreeFooterTagline: "Enjoy a 30 day preview of this Premium Feature",
        PresentFTUEWelcomeFreeFooterStartTrialButton: "Start Trial",
        PresentFTUEWelcomePremiumSlide1Title: "Welcome to Presentation Mode",
        PresentFTUEWelcomePremiumSlide1Text: "Evernote's Presentation mode lets you share your notes in a full-screen view, without the work of creating slides.",
        PresentFTUEWelcomePremiumSlide2Title: "Illuminate Important Ideas",
        PresentFTUEWelcomePremiumSlide2Text: "Your mouse becomes a laser-pointer so you can show people what to focus on while you present.",
        PresentFTUEWelcomePremiumSlide3Title: "View Documents Without Switching Apps",
        PresentFTUEWelcomePremiumSlide3Text: "Zoom in to images and PDFs to show more detail without switching apps.",
        PresentFTUEWelcomePremiumSlide4Title: "PRESENTATION MODE",
        PresentFTUEWelcomePremiumSlide4Text: "Welcome to a new way to show off your notes in business meetings or at home with your family. Presentation mode displays your ideas in a beautiful, full-screen view that lets your content shine.",
        PresentFTUEWelcomePremiumSlide4OkButton: "Get Started",
        PresentFTUEWelcomePremiumFooterTagline: "Evernote Premium Feature",
        PresentFTUEWelcomePremiumFooterOkButton: "OK",
        PresentFTUETrialEndTitle: "PRESENTATION MODE",
        PresentFTUETrialEndText1: "Your complimentary 30-day period has ended.",
        PresentFTUETrialEndText2: "Upgrade to Evernote Premium for access to this and other great Premium features.",
        PresentFTUETrialEndGoPremium: "Go Premium",
        PresentDefaultNoteTitle: "Untitled Note",
        PresentAllNotesUnavailable: "No notes are available for the current presentation. They may have been deleted or an unknown error occured. Please exit the presentation and try starting a new one.",
        PresentExit: "Exit Presentation",
        PresentImageUnavailable: "image unavailable"
    };
    this.isNight = false;
};

PresentationUIController.prototype.getTitles = function(callback){
    var _this = this;
    var defaultTitle = this.resources.PresentDefaultNoteTitle;
    window.getNoteTitle(this.getCurrentNoteGuid(), function(currentTitle){
        window.getNoteTitle(_this.getNextNoteGuid(), function(nextTitle){
            window.getNoteTitle(_this.getPreviousNoteGuid(), function(previousTitle){
                callback(previousTitle,currentTitle,nextTitle);
            }, callback.bind(null, defaultTitle, currentTitle, nextTitle));
        }, callback.bind(null, defaultTitle, currentTitle, defaultTitle));
    }, callback.bind(null, defaultTitle, defaultTitle, defaultTitle));
};

PresentationUIController.prototype.start = function(guids, index, callback){
    if(!this.started){
        $encpJquery('html').css('cursor','default');
        $encpJquery('body').css('cursor','default');
        $encpJquery('#ENCPClone').remove();
        this.firstTime = true;

        if (window.localizedStrings) $encpJquery.extend(this.resources, window.localizedStrings); //Update strings
        
        this.stack = [];
        this.stack.push({
            guids: guids,
            currentIndex : index
        });
        this.loadNote(callback);
        var _this = this;
        $encpJquery(document).on('keydown.presentationmode',function(e){
            if(_this.showingDocumentViewer || _this.showingFTUE){
                return;
            }
            if(e.keyCode == 37){
                _this.onPreviousNoteRequested();
                e.preventDefault();
            }
            else if(e.keyCode == 39){
                _this.onNextNoteRequested();
                e.preventDefault();
            }
        });

        $encpJquery(document).on('drop',function(e){
            e.preventDefault();
            return;
        });
        $encpJquery(document).on('dragover',function(e){
            e.preventDefault();
            return;
        });

        this.started = true;
    }
};

PresentationUIController.prototype.getCurrentNoteGuid = function(){
    var cur = this.stack[this.stack.length-1] || {};
    if(cur.guids){
        return cur.guids[cur.currentIndex];
    }
    else if(cur.guid){
        return cur.guid;
    }
    else {
        return null;
    }
}

PresentationUIController.prototype.getNextNoteGuid = function(){
    var cur = this.stack[this.stack.length-1] || {};
    if(cur.guids){
        return cur.guids[(cur.currentIndex+1)%cur.guids.length];
    }
    else {
        return null;
    }
};

PresentationUIController.prototype.getPreviousNoteGuid = function(){
    var cur = this.stack[this.stack.length-1] || {};
    if(cur.guids){
        return cur.guids[(cur.currentIndex+cur.guids.length-1)%cur.guids.length];
    }
    else {
        return null;
    }
};

PresentationUIController.prototype.showUI = function() {
    _this = this;

    this.backButtonView = new BackButtonView(this.resources);
    this.backButtonView.isEnabled = false;
    this.backButtonView.showUI();
    this.backButtonView.clicked.add(this.onGoBackRequested,this);
    this.backButtonView.showCursorRequested.add(this.onShowCursorRequested,this);
    this.backButtonView.hideCursorRequested.add(this.onHideCursorRequested,this);
    this.previousButtonView = new PreviousNoteButtonView(this.resources);
    this.previousButtonView.showUI();
    this.previousButtonView.clicked.add(this.onPreviousNoteRequested,this);
    this.previousButtonView.showCursorRequested.add(this.onShowCursorRequested,this);
    this.previousButtonView.hideCursorRequested.add(this.onHideCursorRequested,this);
    this.nextButtonView = new NextNoteButtonView(this.resources);
    this.nextButtonView.showUI();
    this.nextButtonView.clicked.add(this.onNextNoteRequested,this);
    this.nextButtonView.showCursorRequested.add(this.onShowCursorRequested,this);
    this.nextButtonView.hideCursorRequested.add(this.onHideCursorRequested,this);
    this.pageUpButtonView = new PageUpButtonView(this.resources);
    this.pageUpButtonView.showUI();
    this.pageUpButtonView.clicked.add(this.onScrollUpRequested,this);
    this.pageUpButtonView.showCursorRequested.add(this.onShowCursorRequested,this);
    this.pageUpButtonView.hideCursorRequested.add(this.onHideCursorRequested,this);
    this.pageDownButtonView = new PageDownButtonView(this.resources);
    this.pageDownButtonView.showUI();
    this.pageDownButtonView.clicked.add(this.onScrollDownRequested,this);
    this.pageDownButtonView.showCursorRequested.add(this.onShowCursorRequested,this);
    this.pageDownButtonView.hideCursorRequested.add(this.onHideCursorRequested,this);
    this.toolbarView = new ToolbarView(this.resources);
    this.toolbarView.showUI();
    this.toolbarView.cursorChangeRequested.add(this.onCursorChangeRequested,this);
    this.toolbarView.exitRequested.add(this.onExitRequested,this);
    this.toolbarView.changeThemeRequested.add(this.onChangeThemeRequested,this);
    this.toolbarView.changeMonitorRequested.add(this.onChangeMonitorRequested,this);
    this.toolbarView.showCursorRequested.add(this.onShowCursorRequested,this);
    this.toolbarView.hideCursorRequested.add(this.onHideCursorRequested,this);
    
    // ------Temporary for testing
    // window.presentationUI = this;
    // $encpJquery(document).on('keydown.presentation',function(e){
    //     if(e.keyCode == 84 && e.altKey && e.shiftKey && e.ctrlKey) { //T
    //         _this.showFTUE('presentationWelcomeFree');
    //     } else if(e.keyCode == 82 && e.altKey && e.shiftKey && e.ctrlKey) { //R
    //         _this.showFTUE('presentationWelcomePremium');
    //     } else if(e.keyCode == 69 && e.altKey && e.shiftKey && e.ctrlKey) { //E
    //         _this.showFTUE('presentationTrialEnd');
    //     }
    // });
    // ------

    this.pointerObserverStarted = false;
    if (Modernizr.webgl){
        try {
            this.pointer = new Pointer();
        }
        catch(e){
            console.log(e);
            this.pointer = new Pointer2D();
        }
    } else {
        this.pointer = new Pointer2D();
    }


    this.lastCursorPos = {x:0,y:0};
    this.lastCursorTime = 0;
    this.hiddenFromLackOfMovement = false;

    $encpJquery(window).on('scroll.presentationmode',_.bind(this.onScroll,this));

    var cursorType = localStorage.getItem("cursorType");
    if(cursorType == "undefined" || !cursorType ){
        cursorType = "blue"
    }

    if(this.pointer) {
        $encpJquery(this.pointer.container).hide();
        this.oldCursor = cursorType;
        this.pointer.show();
        this.onCursorChangeRequested(cursorType);
        this.pointer.enabled = false;
    }
    this.toolbarView.onCursorChangeClick(cursorType);
};

PresentationUIController.prototype.onScroll = function(){
    if(this.showingDocumentViewer || this.showingFTUE){return;}
    var pageUpHidden = $encpJquery(window).scrollTop() == 0;
    var pageDownHidden = $encpJquery(window).scrollTop() + window.innerHeight >= $encpJquery(document).height()-1;

    if(pageUpHidden){
    	if(!this.pageUpButtonView.overrideWithin){
    		this.pageUpButtonView.disable();	
    	}        
    }
    else {
    	if(!this.pageUpButtonView.overrideWithin){
    		this.pageUpButtonView.enable();
    	}
    }

    if(pageDownHidden){
        this.pageDownButtonView.disable();
    }
    else {
        this.pageDownButtonView.enable();
    }

    if(pageDownHidden && !(pageDownHidden && pageUpHidden) && (this.getNumberOfDocsAtStackLevel() > 1) && !this.isLoading){
        this.showEndOfNoteMessage()
    }
    else {
        this.hideEndOfNoteMessage()
        this.showingEndNoteMessage = false;
    }
};

PresentationUIController.prototype.showFTUE = function(specificView, callback) {
    if (!this.dialogView) {
        this.dialogView = new DialogView(this.resources);
        this.dialogView.exitRequested.add(this.onExitRequested,this);
        this.dialogView.showFTUEComplete.add(this.showFTUEComplete,this);
    }
    if (this.pointer) {
        this.pointer.hide();
        this.pointer.enabled = false;
        this.disableAllUI();
    }
    this.showingFTUE = true;
    if (callback) this.FTUECallback = callback;
    this.dialogView.showFTUE(specificView);
};

PresentationUIController.prototype.showFTUEComplete = function(noCallback) {
    this.showingFTUE = false;
    if (this.pointer) {
        this.enableAllUI();
        this.pointer.enabled = true;
        this.pointer.show();
    }
    if (this.FTUECallback && !noCallback) {
        this.FTUECallback();
        this.FTUECallback = null;
    }
    if(this.shouldShowUI){
		this.showUIForABit();
		this.shouldShowUI = false;
	}
};    

PresentationUIController.prototype.showEndOfNoteMessage = function(){
    var _this = this;
    if(!this.showingEndNoteMessage){
        this.showingEndNoteMessage = true;
        $encpJquery(document.body).append('<div class="endNoteMessage">'+this.resources.PresentEndOfNote.replace("{0}","&rarr;")+' "'+this.nextTitle+'"</div>');
        $encpJquery('.endNoteMessage').hide();
        $encpJquery('.endNoteMessage').click(function(){
            if(!this.complete){
                this.complete = true;
                _this.onNextNoteRequested();
                $encpJquery('.endNoteMessage').fadeOut(1000,function(){
                    $encpJquery(this).remove();
                });
            }
        });
        $encpJquery('.endNoteMessage').hover(function(){
            if(!this.complete){
                $encpJquery('.endNoteMessage').stop(true,false)
                $encpJquery('.endNoteMessage').opacity(100);
                this.endNoteHover = true;
            }
            _this.onHideCursorRequested(true)
        },function(){
            _this.onShowCursorRequested(true)
            $encpJquery('.endNoteMessage').fadeOut(1000,function(){
                $encpJquery(this).remove();
            });
        })
        $encpJquery('.endNoteMessage').css('left',(window.innerWidth-$encpJquery('.endNoteMessage').width())/2)
        $encpJquery('.endNoteMessage').fadeIn(
            {complete:function(){
                window.setTimeout(function(){
                    if(!this.endNoteHover){
                        $encpJquery('.endNoteMessage').fadeOut(1000,function(){
                            $encpJquery(this).remove();
                        });
                    }
                }, 3500);
            }}
        );

    }
};

PresentationUIController.prototype.hideEndOfNoteMessage = function(){
    var _this = this;
    if(this.showingEndNoteMessage){
        $encpJquery('.endNoteMessage').fadeOut(1000,function(){
            $encpJquery(this).remove();
        });
    }
};

PresentationUIController.prototype.resize = function(){
    if (this.pointer) this.pointer.onWindowResize();
    if(window.notePresenter){
        window.notePresenter.updateLayout();
    }
};

PresentationUIController.prototype.onGoBackRequested = function(){
    if(this.isLoading){
        return;
    }
    this.lastCursorTime = 0;
    this.stack.pop();
    this.loadNote();
};

PresentationUIController.prototype.getBackTitle = function(callback) {
    var title = 0;
    if(this.stack.length>1){
        var s = this.stack[this.stack.length-2];
        var curGuid = s.guid
        if(s.guids){
            curGuid = s.guids[s.currentIndex];
        }
        window.getNoteTitle(curGuid, callback, callback.bind(null, this.resources.PresentDefaultNoteTitle));
    }
    else {
        callback("");
    }
};

PresentationUIController.prototype.onDocumentViewerExited = function(){
    this.showingDocumentViewer = false;
    this.toolbarView.enabled = true;
    this.pointer.show();
    this.toolbarView.setCursorIcon(this.pointer.currentCursor);
    this.pointer.enabled = true;
    this.enableAllUI();
    this.documentViewer.destroy();
    this.documentViewer = null;
};

PresentationUIController.prototype.onShowCursorRequested = function(enable){
    if(enable){ this.pointer.enabled = true; }
    this.pointer.show();
};

PresentationUIController.prototype.onHideCursorRequested = function(disable){
    this.pointer.hide(null,true);
    if(disable){ this.pointer.enabled = false; }
};

PresentationUIController.prototype.onCursorChangeRequested = function(type,e){
    this.pointer.changeCursor(type);
    this.pointer.render();
    this.lastCursorTime = -2;
    this.pointer.show();
    this.hiddenFromLackOfMovement = false;
    this.toolbarView.setCursorIcon(type);
    if(this.documentViewer){
        if(this.documentViewer.toolbar){
            this.documentViewer.toolbar.setCursorIcon(type);
        }
    }
};

PresentationUIController.prototype.onExitRequested = function(){
    window.presentationWindowClosed(function(){
        console.log("Presentation mode exited");
    });
    this.destroy();
    if(window.top['require'] !== undefined || window.top['nodeRequire'] !== undefined){
        var gui = (window.top.nodeRequire || window.top.require)('nw.gui');
        gui.Window.get().close();
    }
    window.location = window.location;
};

PresentationUIController.prototype.makeDark = function(preventShow){
    if(!this.isNightModeAllowed){
        this.makeBright(preventShow);
        return false;
    }
    if(!this.isNight){
        this.switchStyle();
    }
    $encpJquery('#nightStyleSheet').attr('rel','stylesheet');
    $encpJquery('#nightStyleSheet').prop('disabled', false);
    $encpJquery('#defaultStyleSheet').attr('rel','alternate stylesheet');
    $encpJquery('#defaultStyleSheet').prop('disabled', true);
    this.toolbarView.setNightModeTooltip(this.resources.PresentTooltipDeactivateNightMode,preventShow);
    this.isNight = true;
    return true;
}

PresentationUIController.prototype.makeBright = function(preventShow){
    if(this.isNight){
        this.switchStyle();
    }
    $encpJquery('#nightStyleSheet').attr('rel','alternate stylesheet');
    $encpJquery('#nightStyleSheet').prop('disabled', true);
    $encpJquery('#defaultStyleSheet').attr('rel','stylesheet');
    $encpJquery('#defaultStyleSheet').prop('disabled', false);
    this.toolbarView.setNightModeTooltip(this.resources.PresentTooltipActivateNightMode,preventShow);
    this.isNight = false;
}

PresentationUIController.prototype.switchStyle = function(){
    var _this = this;
    var nextStyle = 0;
    if(this.presenter.styleSheets.length == 0){
        this.presenter.setupStyleSheets();
    }

    $encpJquery.each(this.presenter.styleSheets,function() {
        nextStyle++;
        if (!this.disabled) {
            _this.presenter.log('current style : ' + $encpJquery(this).attr('title'));
            return false;
        }
    });
    if (nextStyle >= this.presenter.styleSheets.length) nextStyle = 0;
    var s = $encpJquery(this.presenter.styleSheets[nextStyle]).attr('title');
    this.presenter.switchStyle(s);
}

PresentationUIController.prototype.onChangeThemeRequested = function(e){
    this.lastCursorTime = 0;
        
    if(!this.isNight){
        if(this.makeDark()){
            Analytics.reportEvent('presentation_mode', 'tools', 'night_mode_on');
            localStorage.setItem("night_mode",true);
        }
    }
    else {
        this.makeBright();
        Analytics.reportEvent('presentation_mode', 'tools', 'night_mode_off');
        localStorage.setItem("night_mode",false);
    }
};

PresentationUIController.prototype.onChangeMonitorRequested = function(){

};

PresentationUIController.prototype.getNumberOfDocsAtStackLevel = function(){
    var cur = this.stack[this.stack.length-1] || {};
    if(!cur.guids){
        return 1;
    }
    return cur.guids.length;
}

PresentationUIController.prototype.onNextNoteRequested = function(){
    if(this.isLoading){
        return;
    }
    this.lastCursorTime = 0;
    var cur = this.stack[this.stack.length-1] || {};
    if(!cur.guids){
        return;
    }
    this.hideAllUI();
    this.nextButtonView.hide();
    this.stack.push({guids:cur.guids,currentIndex: cur.currentIndex});
    cur = this.stack[this.stack.length-1];
    cur.currentIndex = (cur.currentIndex+1)%cur.guids.length;
    Analytics.reportEvent('presentation_mode', 'navigation', 'next_note');
    this.loadNote(null);
};

PresentationUIController.prototype.onPreviousNoteRequested = function(){
    var cur;

    if (this.isLoading) return;
    cur = this.stack[this.stack.length - 1] || {};
    if (!cur.guids) return;

    this.hideAllUI();
    this.previousButtonView.hide();

    this.lastCursorTime = 0;
    this.stack.push({guids:cur.guids, currentIndex: cur.currentIndex});
    cur = this.stack[this.stack.length - 1];
    cur.currentIndex = (cur.currentIndex + cur.guids.length - 1) % cur.guids.length;
    Analytics.reportEvent('presentation_mode', 'navigation', 'previous_note');
    this.loadNote(null);
};

PresentationUIController.prototype.startPointerObserver = function() {
    if(!this.pointerObserverStarted){
        this.timerId = window.setInterval(_.bind(this.observePointer,this),200);
        this.pointerObserverStarted = true;
    }
};

PresentationUIController.prototype.observePointer = function() {
    this.onScroll();
    if(this.pointer && this.pointer.enabled){
        if(Math.sqrt(Math.pow(this.pointer.mouseX-this.lastCursorPos.x,2)+Math.pow(this.pointer.mouseY-this.lastCursorPos.y,2))<3){
            this.lastCursorTime += .2
        }
        else {
            this.lastCursorTime = 0;
            if(this.hiddenFromLackOfMovement) {
                if(this.shouldMouseBeVisible(this.pointer.mouseX,this.pointer.mouseY)){
                	if(!this.isOverImage){
                    	this.pointer.show();
                	}
                    this.hiddenFromLackOfMovement = false;
                }
                else {
                	this.pointer.hide();
                }
            }
        }
        this.lastCursorPos = {x:this.pointer.mouseX,y:this.pointer.mouseY};

    	if(this.lastCursorTime > 2){
            if(!this.hiddenFromLackOfMovement ){
                if(!this.isOverImage){
                    if(this.pointer.isVisible){
                    	if(!this.hiddenFromLackOfMovement){
                    		this.pointer.hide('none');
                        	this.pointer.autoHidden = true;
                    		this.hiddenFromLackOfMovement = true;	
                    	}
                    }
                }
                
            }
        }
        else if(this.lastCursorTime > .1){
            if(!this.hiddenFromLackOfMovement ){
                if(this.isOverImage){
                    if(this.pointer.isVisible){
                        this.pointer.hide('pointer');
                        this.pointer.autoHidden = true;
                    }
                }
                else {
                    if(this.pointer.isVisible){
                        //this.pointer.hide('none');
                    }
                }
                //this.hiddenFromLackOfMovement = true;
            }
        }
        else {
            if(this.isOverImage) {
                if(!this.pointer.isVisible && !this.isLoading) {
                    this.pointer.show();
                }
            }
        }
        if(this.lastCursorTime > 4){
            //this.hideAllUI();
        }
    }
};

PresentationUIController.prototype.shouldMouseBeVisible = function(x,y){
    return this.previousButtonView.shouldMouseBeVisible(x,y) && this.nextButtonView.shouldMouseBeVisible(x,y) && this.pageUpButtonView.shouldMouseBeVisible(x,y) && this.pageDownButtonView.shouldMouseBeVisible(x,y);
}

PresentationUIController.prototype.enableAllUI = function(){
    if(this.stack.length>1){
        this.backButtonView.show();
    }

    var cur = this.stack[this.stack.length-1] || {};
    if(cur.guids && cur.guids.length > 1){
        this.previousButtonView.isVisible = true;
        this.nextButtonView.isVisible = true;
    }
    else {
        this.previousButtonView.isVisible = false;
        this.nextButtonView.isVisible = false;
    }
    this.pageUpButtonView.enable();
    this.pageDownButtonView.enable();
    this.toolbarView.enable();
};

PresentationUIController.prototype.disableAllUI = function(){
    this.backButtonView.hide();
    this.previousButtonView.hide();
    this.nextButtonView.hide();
    this.pageUpButtonView.disable();
    this.pageDownButtonView.disable();
    this.toolbarView.disable();
};

PresentationUIController.prototype.hideAllUI = function(callback){
    this.hideAllCaptions();
    this.backButtonView.hide();
    this.backButtonView.overrideWithin = false;
    this.previousButtonView.hide();
    this.previousButtonView.overrideWithin = false;
    this.nextButtonView.hide();
    this.nextButtonView.overrideWithin = false;
    this.pageUpButtonView.fadeOut();
    this.pageUpButtonView.overrideWithin = false;
    this.pageDownButtonView.fadeOut();
    this.pageDownButtonView.overrideWithin = false;
    this.toolbarView.fadeOut();
    this.toolbarView.overrideWithin = false;
};

PresentationUIController.prototype.loadNote = function(callback){
    //window.perfstart = Date.now();
    this.hideAllCaptions();
    if(this.currentlyViewing == this.getCurrentNoteGuid()){
        console.log("trying to load same note");
        return;
    }
    this.currentlyViewing = this.getCurrentNoteGuid();
    this.isLoading = true;
    var _this = this;

    var Binary = {};
    Binary.toObjectURL = function (source, offset, len, properties) {
        var blob,
            url,
            bytes;

        try {
            if (source instanceof Blob) {
                blob = source;
            } else if (offset) {
                len = len || source.length;
                bytes = source.subarray(offset, len);
                blob = new Blob([bytes], properties);
            } else {
                if (!Array.isArray(source)) source = [source];
                if (properties) blob = new Blob(source, properties);
                else blob = new Blob(source);
            }
            url = URL.createObjectURL(blob);
        } catch (ex) {}

        return url;
    };

    var launchPDFinExternalViewer = function (resource, callback) {
        var w = window.top || window;
        var req = w.nodeRequire || w.require;
        if(req !== undefined){
            var gui = req('nw.gui');
            var fs = req('fs');
            var path = req('path');
            var os = req('os');
            var Buffer = req('buffer').Buffer;
            var attachmentPath = User && User.attachmentPath;
            var dir;

            if (attachmentPath) {
                Analytics.reportEvent('presentation_mode', 'navigation', 'open_external_pdf');
                dir = path.join(attachmentPath, 'PresentationMode');
                if (!fs.existsSync(dir)) fs.mkdirSync(dir);
                fs.readdir(dir, function (err, files) {
                    if (err) return;
                    files.forEach(function (file) {
                        fs.unlink(path.join(dir, file), function (err) {
                            if (err) console.log('Failed to delete temp presentation mode file: ' + path.join(dir, file));
                        });
                    });
                    window.getResource(resource.url, function (pdf) {
                        var filepath = path.join(dir, pdf.filename);
                        var data = Array.prototype.slice.call(pdf.data, 0);
                        var buffer = new Buffer(data);
                        fs.writeFile(filepath, buffer, function (err) {
                            gui.Shell.openItem(filepath);
                            if (typeof callback === 'function') callback();
                        });
                    });
                });
            }
        }
    };

    var $mask = $encpJquery('<div class="loading-mask disabled"><div class="waitingLoader"></div></div>');

    var enableLoadingMask = function (dom) {
        var $dom = $encpJquery(dom);
        var domOffset = $dom.offset();
        
        $mask.find('.waitingLoader').css('position', 'absolute');
        $mask.css('margin', '0px').css('position', 'absolute').css('left', domOffset.left + 'px').css('top', domOffset.top + 'px');
        $mask.height($dom.height()).width($dom.width());
        $mask.appendTo(document.body);
    };

    var disableLoadingMask = function (dom) {
        $mask.detach();
    };

    var setupNote = function(wrapperDiv,notediv,noteInfo) {
        _this.getTitles(function(previousTitle,currentTitle,nextTitle){
            $encpJquery('#ENCPClone').html('');
            noteDiv = $encpJquery("<div>", {
                id: "ENCPNote",
                html: notediv.html()
            });

            wrapperDiv.append(noteDiv);
            wrapperDiv.hide();
            $encpJquery("body").append(wrapperDiv);
            $encpJquery(wrapperDiv).css('opacity',0);

            var noteTitle = currentTitle;
            var updateDate = "Totally fake date";

            /*** Run Cleaner ***/
            var cleaner = new ENCPClean();
            cleaner.postprocess(noteDiv[0], {
                title: noteTitle,
                updated: updateDate,
                source: noteInfo.source,
                author: noteInfo.author,
                sourceURL: noteInfo.sourceURL,
                contentClass: noteInfo.contentClass
            });

            /*** Show Presentation ***/
            if (window.notePresenter == null) {
                window.setupNotePresenter();
                window.notePresenter = window.encpPresenter;
            }
            
            ENCPDeferred
              .doNow(function() {
                window.notePresenter.presentationPageLoaded(noteDiv[0]);
              })
              .then(function() {
                window.encpPlatform.didFinishPageLoad();
                window.notePresenter.parseMediaAndNotify();
              })
              .done();

            window.scrollTo(0, 0);
            wrapperDiv.show();
            if(callback){
                callback();
            }
            _this.presenter = window.notePresenter;
            var cur = _this.stack[_this.stack.length-1] || {};
            if(cur.guids && cur.guids.length > 1){
                _this.previousButtonView.isVisible = true;
                _this.previousButtonView.setTitle(previousTitle);
                _this.nextButtonView.isVisible = true;
                _this.nextButtonView.setTitle(nextTitle);
            }
            else {
                _this.previousButtonView.hide();
                _this.nextButtonView.hide();
            }
            _this.nextTitle = nextTitle;

			if(_this.stack.length == 1 || (_this.stack.length > 1 && _this.stack[_this.stack.length-1].guids)) {
        		_this.backButtonView.hide(true);
    			_this.backButtonView.isEnabled = false;
        	}

            _this.getBackTitle(function(title){
                _this.backButtonView.setTitle(title);
            });

            $encpJquery('.encp-media-container img').each(function(a,b){
                $encpJquery(this).css("cursor","inherit");
            });


            $encpJquery('.encp-media-container img').click(function(){
                var resource = _this.noteResources[this.src];
                var i = 0;
                var images = [];

                if($encpJquery(this).hasClass('no-doc-viewer')) return;

                $encpJquery('.encp-media-container img').not('.no-doc-viewer').each(function(a,b){
                    images.push({image:this,filename:this.src.substr(this.src.lastIndexOf('/')+1)});
                });

                // Find the starting image index for the doc viewer
                for(i = 0; i < images.length; i++){
                    if(this == images[i].image){
                        break;
                    }
                }

                if (resource && resource.mimeType === 'application/pdf') {
                    enableLoadingMask(this);
                    launchPDFinExternalViewer(resource, function () {
                        setTimeout(function () { disableLoadingMask(this); }.bind(this), 500);
                    });
                } else {
                    _this.showingDocumentViewer = true;
                    _this.disableAllUI();
                    var dv = new DocumentViewerController(_this.pointer,_this.resources,images,i);
                    _this.documentViewer = dv;
                    dv.exited.add(_this.onDocumentViewerExited,_this);
                    dv.start();
                    _this.toolbarView.enabled = false;
                }
            });

            $encpJquery('li:has(ul)').addClass('sublist');
            $encpJquery('li:has(ol)').addClass('sublist');

            $encpJquery('.encp-media-container img').hover(function() {
                if (_this.isLoading) return;
                if(!$encpJquery(this).hasClass('no-doc-viewer')) _this.isOverImage = true;
                _this.showCaptionOverImage(this);

            }, function(){
                if(!_this.isLoading){
                    _this.isOverImage = false;
                    _this.hideCaptionOverImage(this);
                    _this.pointer.show(true);
                }
            })
            _this.startPointerObserver();

            $encpJquery('a').each(function(i,v){
                if(this.href.indexOf('evernote:///view/')==0){
                    _this.prepareNoteLink(this);
                }
                else if(this.href.indexOf('http')==0){
                    $encpJquery(this).hover(function(){
                        _this.onHideCursorRequested();
                    }, function(){
                        _this.onShowCursorRequested();
                    });
                    $encpJquery(this).click(function(e){
                        var w = window.top || window;
                        var req = w.nodeRequire || w.require;
                        if(req !== undefined){
                            // Load native UI library
                            var gui = req('nw.gui');
                            Analytics.reportEvent('presentation_mode', 'navigation', 'open_external_link');
                            gui.Shell.openExternal(this.href)
                            e.preventDefault();
                        }
                    })
                }
                else {
                    //disable links we don't know what they do so they don't shift our browser to some place they can't get out of
                    $encpJquery(this).click(function(e){
                        e.preventDefault();
                    })
                    return;
                }
            });

            if(_this.stack.length>1){
                _this.showBackButton();
            }
            else {
                _this.hideBackButton();
            }
            _this.isLoading = false;
            window.notePresenter.updateLayout();

            if(_this.isWebSource()){
                _this.preventNightMode();
            }
            else {
                _this.allowNightMode();
            } 


            _this.hideWaiting(function(){
                if(_this.pointer) {
                    //$encpJquery(_this.pointer.container).show();
                    _this.pointer.clear();
                    _this.pointer.show();
                    if(_this.oldCursor){
                        _this.onCursorChangeRequested(_this.oldCursor);
                        _this.oldCursor = null;
                    }
                    _this.pointer.enabled = true;
                }
                setTimeout(function(){
                    $encpJquery(wrapperDiv).tween({
                        alpha:{
                            start: 0,
                            stop: 100,
                            time: 0,
                            duration: 1,
                            units: 'px',
                            effect: 'easeOut'
                        }
                    }).play();
                    if(_this.firstTime){_this.shouldShowUI = true;}
                    _this.showFTUE();
                    if(_this.firstTime){
                        var nightmode = localStorage.getItem("night_mode");
                        if(nightmode === "true"){
                            _this.makeDark(true);
                        }
                        _this.firstTime = false;
                    }
                    else {
                    	if(_this.backButtonView.isVisible && _this.usedNoteLink){
                            _this.backButtonView.isEnabled = true;
                    		_this.showBackButtonABit();
                    		_this.usedNoteLink = false;
                    	}
                    }
                },200)
            });
        });
    };

    var doLoad = function() {
        _this.cleanHtmlElementClasses();
        this.currentlyViewing = _this.getCurrentNoteGuid();

        _this.objectUrls.forEach(function (url) {
            URL.revokeObjectURL(url);
        });
        _this.objectUrls = [];

        function getNoteAsHtml_Error() {
            // Unable to load note html due to thrift error or user deleting note
            var presentState;
            var badIndex;
            var guids;
            var priorState;
            var priorIndex;

            if (_this.stack.length > 1) {
                presentState = _this.stack[_this.stack.length - 1];
                badIndex = presentState.currentIndex;
                guids = presentState.guids;
                priorState = _this.stack[_this.stack.length - 2];

                if (badIndex == 0) {
                    presentState.currentIndex = (priorState.currentIndex == 1) ? guids.length - 1 : 1;
                } else if (badIndex == guids.length - 1) {
                    presentState.currentIndex = (priorState.currentIndex == 0) ? badIndex - 1 : 0;
                } else {
                    presentState.currentIndex += (priorState.currentIndex < badIndex) ? 1 : -1;
                }
                guids.splice(badIndex, 1);

                _this.stack = _this.stack.filter(function (state, stackIndex) {
                    if (state.currentIndex == badIndex) return false;
                    if (state.currentIndex > badIndex) state.currentIndex--;
                    return (stackIndex == 0 || state.currentIndex != _this.stack[stackIndex - 1].currentIndex);
                });

                window.getNote(_this.getCurrentNoteGuid(), getNoteAsHtml_Success, getNoteAsHtml_Error);
            } else {
                getNoteAsHtml_Success({
                    html: [
                        '<html><body>',
                        '<div class="encp-error">',
                        '<img src="images/broken_notelink.svg" class="encp-error-icon">',
                        '<p>',
                        _this.resources.PresentAllNotesUnavailable,
                        '</p>',
                        '<a onclick="javascript:presentationUI.onExitRequested();">',
                        _this.resources.PresentExit,
                        '</a>',
                        '</div>',
                        '</body></html>'
                    ].join('\n')
                });
            }
        }

        function getNoteAsHtml_Success(noteInfo) {
            var note = noteInfo.html;

            if (note == null || note.length == 0) return getNoteAsHtml_Error();

            note = note.replace(/<body[^>]*>/i,'<div class="ennote-target">');
            note = note.replace('</body>','</div>');
            var el = document.createElement( 'div' );
            el.innerHTML = note;
            var body = $encpJquery('.ennote-target',el).get(0);

            //NOTE: THIS CODE IS MINIMUMAL SETUP TO SIMULATE THE EVERNOTE CLIENT STARTING THE PRESENTATION WITH SOME ENML
            note = '<div>'+body.innerHTML+'</div>';

            $encpJquery("html").css("overflow-x", "hidden")

            /*** Duplicating HTML For Presentation ***/
            var wrapperDiv = $encpJquery("<div>", { id: "ENCPClone" });

            var notediv = $encpJquery(note);

            function getResources_Success(resources) {
                _this.noteResources = {};
                var imagesToLoad = [];
                $encpJquery('img[src ^=en-resource]',notediv).each(function(){
                    console.log(this.src); // Temporarily log resource URLs to console for PDF markup development
                    imagesToLoad.push(this);
                });

                // Remove trailing colon and number from resource.id
                resources.forEach(function (resource) {
                    var id = resource.id.match(/(^.*):\d+$/);
                    resource.url = resource.id;
                    if (id && id.length > 1) resource.id = id[1];
                });

                imagesToLoad.forEach(function (image) {
                    // Remove trailing colon and number from image.src and resource.id
                    var src = image.src.match(/(^.*):\d+$/);
                    src = (src && src.length > 1) ? src[1] : image.src;
                    resources.some(function (resource) {
                        var objectUrl;
                        var placeholder;
                        if (src == resource.id) {
                            if (resource.data && resource.data.length > 0) {
                                objectUrl = Binary.toObjectURL(resource.data, null, null, {type: resource.mimeType});
                                _this.objectUrls.push(objectUrl);
                                image.src = objectUrl;
                            } else if (resource.base64 && resource.base64.length > 0) {
                                // Support test data
                                image.src = resource.base64;
                            } else {
                                $encpJquery(image).replaceWith([
                                    '<span class="attachment">',
                                    //'<a href="#" data-url="',
                                    //resource.id,
                                    //'">',
                                    '<span class="icon"></span>',
                                    truncateFilename(resource.filename || 'untitled'), 
                                    //'</a>',
                                    '</span><br>'
                                ].join(''));
                            }
                            _this.noteResources[image.src] = resource;
                            return true;
                        }
                    });
                });

                window.encpPlatform.markBrokenNoteLinksAsync(notediv).then(carryOn, carryOn);

                function carryOn() {
                    setupNote(wrapperDiv,notediv,noteInfo);
                }
            }

            function getResources_Error() {
                return getResourcesSuccess([]);
            }

            function truncateFilename(filename) {
                if (filename.length > 32) {
                    filename = filename.substr(0, 16) + '&#133;' + filename.substr(filename.length - 16);
                }
                return filename;
            }

            // console.log('Calling getResourcesAsBase64. Time since perfstart: ' + (Date.now() - window.perfstart));
            // var evtstart = Date.now();
            window.getResources(_this.getCurrentNoteGuid(), getResources_Success, getResources_Error);
        }

        window.getNote(_this.getCurrentNoteGuid(), getNoteAsHtml_Success, getNoteAsHtml_Error);
    };

    if(this.pointer) {
        //$encpJquery(this.pointer.container).hide();
        this.oldCursor = this.pointer.currentCursor;
        this.pointer.hide();
        //this.onCursorChangeRequested("default");
        //this.pointer.enabled = true;
    }
    if($encpJquery('#ENCPClone').length){
        $encpJquery('#ENCPClone').tween({
            alpha:{
                start: 100,
                stop: 0,
                time: 0,
                duration: 1,
                units: 'px',
                effect: 'easeOut',
                onStop: function(){
                    $encpJquery('#ENCPClone').remove();
                        _this.showWaiting(function(){
                        doLoad();
                    });
                }
            }
        }).play();

    }
    else {
        _this.showWaiting(function(){
            doLoad();
        });

    }
};

PresentationUIController.prototype.isWebSource = function(){
    var ret = $encpJquery("html").hasClass("websource");
    return ret;
}

PresentationUIController.prototype.allowNightMode = function(){
        this.isNightModeAllowed = true;        
        if(!this.isNight && localStorage.getItem("night_mode") == "true"){
            this.makeDark(true);
        }
        $encpJquery('.presentationThemeButton').show();
}

PresentationUIController.prototype.preventNightMode = function(){
        this.isNightModeAllowed = false;
        $encpJquery('.presentationThemeButton').hide();
        this.makeBright(true);
}

PresentationUIController.prototype.prepareNoteLink = function(noteLink){
    var _this = this;
    $encpJquery(noteLink).hover(function(){
        _this.pointer.hide();
    }, function(){
        _this.pointer.show();
    });
    var link = noteLink.href;
    $encpJquery(noteLink).attr('href','#');
    $encpJquery(noteLink).click(function(e){
        if(_this.isLoading){
            return;
        }
        e.preventDefault();
        window.getNoteId(link,function(targetNoteGuid){
            if (targetNoteGuid == '0') {
                console.log('Unable to retrieve note id for ' + link);
                return;
            }
            _this.stack.push({guid: targetNoteGuid});
            Analytics.reportEvent('presentation_mode', 'navigation', 'open_note_link');
            _this.usedNoteLink = true;
            _this.loadNote();
            window.notePresenter.focused = null;
        }, function onerror(err) {
            console.log('Unable to retrieve note id for ' + link);
            console.log(err);
        })
    });
}

PresentationUIController.prototype.showCaptionOverImage = function(img){
    var resource = this.noteResources[img.src];
    var text = this.resources.PresentClickToExpandImage
    var b = img.getBoundingClientRect();

    if(img.caption) return;

    if($encpJquery(img).hasClass('encrypted-text')) return;

    if(resource){
        text = resource.mimeType === 'application/pdf' ? this.resources.PresentClickToReadPDF : this.resources.PresentClickToExpandImage;
    }
    if ($encpJquery(img).hasClass('broken-image')) {
        img.caption = $encpJquery('<div class="imageCaption" style="top:'+ (b.top-50+$encpJquery(window).scrollTop())+'px; margin-left: -6px;"><img src="images/tooltip_alert.svg" style="display:inline-block; margin-right: 6px; vertical-align: sub">' + this.resources.PresentImageUnavailable + '</div>');
    } else {
        img.caption = $encpJquery('<div class="imageCaption" style="top:'+ (b.top-50+$encpJquery(window).scrollTop())+'px"><img src="images/tooltip_zoom.svg" style="display:inline-block; margin-right: 10px; vertical-align: middle">' + text + '</div>');
    }
    this.hideAllCaptions();
    this.captions.push(img.caption);
    $encpJquery(document.body).append(img.caption);
    $encpJquery(img.caption).fadeOut(0);
    $encpJquery(img.caption).fadeIn();
};

PresentationUIController.prototype.hideCaptionOverImage = function(img){
    if(img.caption){
        var captionToRemove = img.caption;
        img.caption = null;
        this.hideCaption(captionToRemove)
    }
};

PresentationUIController.prototype.hideCaption = function(captionToRemove){
    $encpJquery(captionToRemove).fadeOut({complete:function(){
        $encpJquery(captionToRemove).remove();
    }});
};

PresentationUIController.prototype.hideAllCaptions = function(){
    if(this.captions){
        for(var i in this.captions){
            this.hideCaption(this.captions[i]);
        }
        this.captions = [];
    }
};

PresentationUIController.prototype.showUIForABit = function(){
		this.nextButtonView.showABit();
		this.previousButtonView.showABit();
		this.toolbarView.showABit();
		//this.pageUpButtonView.showABit();
		this.pageDownButtonView.showABit();
}

PresentationUIController.prototype.showBackButtonABit = function(){
		this.backButtonView.showABit();
}

PresentationUIController.prototype.showBackButton = function(){
    this.backButtonView.show();
};

PresentationUIController.prototype.hideBackButton = function(complete){
    this.backButtonView.hide();
};

PresentationUIController.prototype.showWaiting = function(callback){
    this.loaderTitleDiv = $encpJquery('<div class="waitingLoaderTitle"></div>');
    $encpJquery(this.loaderTitleDiv).hide();
    $encpJquery(document.body).append(this.loaderTitleDiv);
    var _this = this;
    window.getNoteTitle(this.getCurrentNoteGuid(), function(currentTitle) {
        if (currentTitle == null || currentTitle == '') currentTitle = _this.resources.PresentDefaultNoteTitle;
        $encpJquery(_this.loaderTitleDiv).html(_this.resources.PresentWaitingLoaderTitle.replace("{0}",'<span class="title">'+currentTitle+'</span>'));
        $encpJquery(_this.loaderTitleDiv).fadeIn();
    }, function onerror() {
        $encpJquery(_this.loaderTitleDiv).html(_this.resources.PresentWaitingLoaderTitle.replace("{0}",'<span class="title">' + _this.resources.PresentDefaultNoteTitle + '</span>'));
        $encpJquery(_this.loaderTitleDiv).fadeIn();
    });
    this.loaderDiv = $encpJquery('<div class="waitingLoader"></div>');
    $encpJquery(this.loaderDiv).hide();
    $encpJquery(document.body).append(this.loaderDiv);
    $encpJquery(this.loaderDiv).fadeIn({complete:callback});
};

PresentationUIController.prototype.hideWaiting = function(complete){
    var _this = this;
    if(this.loaderDiv){
        $encpJquery(this.loaderTitleDiv).fadeOut();
        $encpJquery(this.loaderDiv).fadeOut({complete:function(){
            $encpJquery(_this.loaderTitleDiv).remove();
            $encpJquery(_this.loaderDiv).remove();
            if(complete){complete();}
        }});
    }
    else {
        if(this.pointer) {
            this.pointer.show();
            if(_this.oldCursor){
                _this.onCursorChangeRequested(_this.oldCursor);
                _this.oldCursor = null;
            }
            this.pointer.enabled = true;
        }
        if(complete){complete();}
    }
};

PresentationUIController.prototype.onScrollDownRequested = function(){
    this.presenter.proceedPageDown();
};

PresentationUIController.prototype.onScrollUpRequested = function(){
    this.presenter.proceedPageUp();
};

PresentationUIController.prototype.cleanHtmlElementClasses = function(){
    $encpJquery("html").css("font-size", "" ).removeClass('notesource websource encp-nocontents-in-title');
};

PresentationUIController.prototype.destroy = function(){
    this.objectUrls.forEach(function (url) {
        URL.revokeObjectURL(url);
    });
    this.objectUrls = [];
    this.currentlyViewing = null;
    window.clearInterval(this.timerId);
    this.cleanHtmlElementClasses();
    $encpJquery('.endNoteMessage').remove();
    $encpJquery('.waitingLoader').remove();
    $encpJquery('.waitingLoaderTitle').remove();
    $encpJquery('#ENCPNote').remove();
    $encpJquery('#ENCPClone').remove();
    $encpJquery(window).off("scroll.presentationmode");
    $encpJquery(document).off('keydown.presentationmode')
    if(this.backButtonView){ this.backButtonView.destroy(); }
    if(this.previousButtonView){ this.previousButtonView.destroy(); }
    if(this.nextButtonView){ this.nextButtonView.destroy(); }
    if(this.pageUpButtonView){ this.pageUpButtonView.destroy(); }
    if(this.pageDownButtonView){ this.pageDownButtonView.destroy(); }
    if(this.toolbarView){ this.toolbarView.destroy(); }
    if(this.pointer){ this.pointer.destroy(); }
    if(this.documentViewer){ this.documentViewer.destroy(); }
    if(this.dialogView){ this.dialogView.destroy(); }
    this.started = false;
    if(this.presenter){ this.presenter.destroy(); }
};

