/**
 * @author Tim
 */
FLN.FramesetController = function(){
    var _me = FLN.FramesetController;
    var _module = new FLN.Module(FLN.InitData);
    var _startDate = new Date().getTime();
    var _lastVisitedPage = "";
    var _currentPage = "";
    var _currentTopic = "";
    var _view;
    var _nextButtonEnabled = false;
    var _backButtonEnabled = false;
    var _menuButtonEnabled = false;
	var _completionMessageAlreadyShown = false;
	var _completionCode = ""; //code for completion. only relevent to offline version
    
    //create shortcut for YAHOO.util.Event: 
    var _e = YAHOO.util.Event;
    
    var updateAllView = function(){
		if(!_view){
			//catch all if the refresh button was clicked
			return;
		}		
        _view.setTotalPagesModule(_module.numberOfPagesInDisplay);
        
        _view.setTotalPagesTopic(_currentTopic.numberOfPagesInDisplay);
        
        _view.setModulePageNumber(_currentPage.pageNumber);
        
        _view.setTopicPageNumber(_currentPage.topicPageNumber);
        
        _view.enablePageNumbering(_currentPage.displayPageNumbering);
        
        //update pages complete on the screen
        _view.setNumberOfCompletedPages(_module.getCompletedPagesThatContributeToCompletionArray().length);
        
        //var nextButtonEnabled = _module.getIfNextPageAvailable(_currentPage.id);
        _view.enableNextButton(_nextButtonEnabled);
        
        //var backButtonEnabled = _module.getIfPreviousPageAvailable(_currentPage.id);
        _view.enableBackButton(_backButtonEnabled);
        
        //enable or disable the menu button.
        //var menuButtonEnabled = _module.getIfMenuAvailable(_currentPage.id;
        _view.enableMenuButton(_menuButtonEnabled);
    };
    
    //public methods
    return {
        init: function(){
            //window events. the object reference: "this" should be the execution scope.
			//prevent right clicks?
			if (FLN.Config.disable_right_click == true) {
				_e.on(window, "contextmenu", this.preventDefault, this, true);
				_e.on(document, "contextmenu", this.preventDefault, this, true);
			}		
            _e.on(window, "unload", this.end, this, true);
            _e.on(window, "load", this.framesetLoaded, this, true);
        },
		/**
		 * for preventing default events
		 * @param {Event} e
		 */
		preventDefault: function(e){_e.preventDefault(e);},
        glossaryLoaded: function(){
            this.start();
        },
        framesetLoaded: function(){
            _view = FLN.View();
            _view.loadGlossary();
        },
        start: function(){
			if(!_view){
				//catch all if the refresh button was clicked
				return;
			}
			
			if (FLN.Config.YAHOO_log_reader_on == true) {
				var myLogReader = new YAHOO.widget.LogReader("compact");
				YAHOO.widget.LogReader.VERBOSE_TEMPLATE = "<p>{message}<br/><br/></p>";
			}
            
            //everything has loaded. it's ok to start.
           
            //connect to the LMS
            FLN.ScormAdapter.initialise();
            
			//initialise the assessment controller.
			FLN.AssessmentController.init();
			
            var lesson_status;
            
            if (FLN.ScormAdapter.isInitialised()) {
                lesson_status = FLN.ScormAdapter.getLMSValue("cmi.core.lesson_status");
            }
            else {
                lesson_status = "not attempted";
            }
            
            if (lesson_status == "not attempted") {
                FLN.ScormAdapter.setLMSValue("cmi.core.lesson_status", "incomplete");
                FLN.ScormAdapter.commitLMS();
            }
            
			//if the module has been completed in a previous session, then map that info to the module object.
            if (lesson_status == "completed") {
                _module.completedInPreviousSession = true;
				
				//the completion message will have already been shown
				_completionMessageAlreadyShown = true;
            }
            
            //get various data from the LMS and apply it to the Module.
            //get the completed pages object from suspend_data
            var suspendStr = FLN.ScormAdapter.getLMSValue("cmi.suspend_data");
            if (suspendStr) {
                try {
                    var o = YAHOO.lang.JSON.parse(suspendStr);
                    for (var i in o) {
                        //use yahoo hasOwnProperty here to protect against members added to object prototype
                        if (YAHOO.lang.hasOwnProperty(o, i)) {
                            //look up the abbreviation.
                            var status = FLN.Config.statusAbbreviations[i];
                            for (var j = 0; j < o[i].length; j++) {
                                _module.getPageByShortId(o[i][j]).status = status;
                            }
                        }
                    }
                } 
                catch (e) {
                    //Yahoo.log("Error: Failed to objectify: " + suspendStr + e.message);
                }
            }
            
            //update pages complete on the screen
            _view.setNumberOfCompletedPages(_module.getCompletedPagesThatContributeToCompletionArray().length);
            
            //what should be the first page that loads? Last page visited.
            var lesson_location = FLN.ScormAdapter.getLMSValue("cmi.core.lesson_location");
            var firstPageId = lesson_location ? lesson_location : _module.firstPageId;
            _view.loadPage(firstPageId);
            
            //button events
            _view.setMenuButtonEvent(this.menuButtonClicked, this, true);
            _view.setNextButtonEvent(this.nextButtonClicked, this, true);
            _view.setBackButtonEvent(this.backButtonClicked, this, true);			
			
			//if we are on an LMS, don't enable the exit button
			if (FLN.ScormAdapter.apiEverDiscovered()) {
				_view.makeExitButtonVisible(false); //were on an LMS. Make the exit button invisible				
			}else{
				_view.makeExitButtonVisible(true); //were not on an LMS. Make the exit button visible					
	            _view.setExitButtonEvent(this.exitButtonClicked, this, true);
		        _view.enableExitButton(true); //tell the exit button to enable											
			}

        },
        /**
         * called by FLN.framesetLoaded - say goodbyes to the LMS API.
         */
		getCompletionMessageAlreadyShown : function(){
			return _completionMessageAlreadyShown;
		},
		setCompletionMessageAlreadyShown : function(shown){
			_completionMessageAlreadyShown = shown;
		},
        end: function(){
            if (FLN.ScormAdapter.isInitialised()) {
                var formattedTime = "00:00:00.0";
                if (_startDate != 0) {
                    var currentDate = new Date().getTime();
                    var elapsedSeconds = ((currentDate - _startDate) / 1000);
                    var formattedTime = FLN.Utils.convertTotalSeconds(elapsedSeconds);
                }
                
                FLN.ScormAdapter.setLMSValue("cmi.core.session_time", formattedTime);
                
                FLN.ScormAdapter.finish();
            }
        },
        
        /**
         * called by the page as it loads
         * @param {String} href
         */
        pageLoading: function(href){
            _lastVisitedPage = _currentPage;
            var pageId = FLN.Utils.getFileName(href);
            _currentPage = _module.getPageById(pageId);
            _currentTopic = _module.getTopicByPageById(pageId);
			YAHOO.log(_currentPage.id);
            if (_currentPage.bookmarkable == true) {
                FLN.ScormAdapter.setLMSValue("cmi.core.lesson_location", pageId);
                FLN.ScormAdapter.commitLMS();
            }
            
            if (_currentPage.completionPolicy == "loading") {
                this.setPageStatus(href, "completed", false);
            }
            
            _nextButtonEnabled = _module.getIfNextPageAvailable(_currentPage.id);
            _backButtonEnabled = _module.getIfPreviousPageAvailable(_currentPage.id);
            _menuButtonEnabled = _module.getIfMenuAvailable(_currentPage.id);
            
            updateAllView();

        },
        
        pageLoaded: function(href){
            //updateAllView();
        },
        
        pageUnLoaded: function(href){
            //updateAllView();
        },
        
        nextButtonClicked: function(ev){
            var nextAvailable = _nextButtonEnabled;
            if (nextAvailable == true) {
                this.gotoNextPage();
            }
            else {
                //alert("Next button not enabled (temporary message).");
            }
			_e.preventDefault(ev);
        },
        
        backButtonClicked: function(ev){
            var backAvailable = _backButtonEnabled;
            if (backAvailable == true) {
                this.gotoPreviousPage();
            }
            else {
                //alert("Back button not enabled (temporary message).");
            }
			_e.preventDefault(ev);
        },
        
        menuButtonClicked: function(ev){
            var menuAvailable = _menuButtonEnabled;
            if (menuAvailable) {
                this.gotoMenu();
            }
            else {
                //alert("Menu button not enabled (temporary message).");
            }
			_e.preventDefault(ev);
        },
		
        exitButtonClicked: function(ev){
			//alert("FramsetController.exitButtonClicked()");
			if(confirm("Are you sure you want to exit this course? \n\nOn exiting, your progress information will be lost.")){
				window.top.close(); //use window.top here because we can't know how deeply nested this window is.
			}
			_e.preventDefault(ev);
        },		
        
        gotoNextPage: function(){
            _view.loadPage(_currentPage.nextId);
        },
        
        gotoPreviousPage: function(){
            _view.loadPage(_currentPage.prevId);
        },
        
        gotoMenu: function(){
            _view.loadPage(_module.menuPageId);
        },
        
        gotoTopic: function(id){
			//alert("FramesetController: gotoTopic(): " + id);
            var t = _module.getTopicById(id);
            var firstPage = t.firstPageId;
            _view.loadPage(firstPage);
        },
		/**
		 * Checks if the module is completed, and carries out the appropriate actions on the LMS, taking into account the different completion policies ("allAssessmentsPassed" or "allPagesComplete").
		 * @param {Boolean} commit should the Scorm Adapater be told to commit? True or false.
		 */
        checkForModuleCompletion: function(commit){
			var moduleIsCompleted = _module.calcIfCompletionRequirementMet();
			//YAHOO.log("checkForModuleCompletion(): moduleIsCompleted: " + moduleIsCompleted);
			
			//YAHOO.log(moduleIsCompleted +  ", " + _module.alreadyCompleteThisSession + ", " + _module.completedInPreviousSession + ', ' + FLN.ScormAdapter.isInitialised());
			
			//allPagesComplete
            if (moduleIsCompleted == true && _module.alreadyCompleteThisSession == false && _module.completedInPreviousSession == false) {
			
                if (FLN.ScormAdapter.isInitialised()) {

                    FLN.ScormAdapter.setLMSValue("cmi.core.lesson_status", "completed");

					//if the completion policy is "allAssessmentsPassed" then set a score,
					//this means that the sco will only ever capture the first passing score.
					//Subsequent scores, that are higher than the current set score on the LMS, are irrelevent and are not set.
					
					if (_module.completionPolicy == "allAssessmentsPassed") {
						FLN.ScormAdapter.setLMSValue("cmi.core.score.raw", String(FLN.AssessmentController.getAggregatePercentageScore()));
					}
					
					if(commit == true){
						FLN.ScormAdapter.commitLMS();
					}
                }
				_completionCode = this.generateCompletionCode();
				//alert("1_" + _completionCode);
                _module.alreadyCompleteThisSession = true;
            }			
		},
        setPageStatus: function(href, status, updateView){
            var pageId = FLN.Utils.getFileName(href);
            var page = _module.getPageById(pageId);
            var currentStatus = _currentPage.status;
            //if this is a status change, then do stuff.
            if (currentStatus != status) {
            
                page.status = status;
                
				//a page status has changed, perhaps its enough for module completion.
				this.checkForModuleCompletion(false);
                
                /*
                 * commit the status of pages that aren't "not attempted" to the LMS
                 * create an object of the form {"c":["t00_p01.html","t00_p02.html",...],"i":["asdas.html","sss.html"],...}
                 */
                var pgs = _module.pages;
                var abbrvs = FLN.Config.statusAbbreviations;
                var statusObj = {};
                for (var i in abbrvs) {
                    //use yahoo hasOwnProperty here to protect against members added to object prototype
                    if (YAHOO.lang.hasOwnProperty(abbrvs, i)) {
                        //dont record the default "not attempted"
                        if (abbrvs[i] != "not attempted") {
                            //var a1 = FLN.scoData.getPagesWithStatus(abbrvs[i]);
                            var a1 = FLN.Utils.filterObjectArray(pgs, {
                                status: abbrvs[i]
                            });
                            var a2 = [];
                            for (var j = 0; j < a1.length; j++) {
                                a2.push(a1[j].shortId);
                            }
                            statusObj[i] = a2;
                        }
                        
                    }
                }
                
                var str = YAHOO.lang.JSON.stringify(statusObj);
				//YAHOO.log(YAHOO.lang.dump(statusObj));
                if (FLN.ScormAdapter.isInitialised()) {
                    FLN.ScormAdapter.setLMSValue("cmi.suspend_data", str);
                    FLN.ScormAdapter.commitLMS();
                }
                
                _nextButtonEnabled = _module.getIfNextPageAvailable(_currentPage.id);
                _backButtonEnabled = _module.getIfPreviousPageAvailable(_currentPage.id);
                _menuButtonEnabled = _module.getIfMenuAvailable(_currentPage.id);
                
                if (updateView) {
                    updateAllView();
                }
            }
			//YAHOO.log(_currentPage.id + ", " + _currentPage.status + ", " + _module.getCompletedPagesThatContributeToCompletionArray().length);						
        },
        forceEnableNextButton: function(enable){
            _nextButtonEnabled = enable;
            _view.enableNextButton(enable);
        },
        
        /**
         * gets a glossary item object with particular Id
         * @param {String} id
         * @return {Object} resultObj object with two properties: title and definition
         */
        getGlossaryItem: function(id){
            // remove leading & trailing spaces - dw
            id = YAHOO.lang.trim(id);
            var resultObj = {
                title: _view.getGlossaryTitle(id),
                definition: _view.getGlossaryDefinition(id)
            };
            return resultObj;
        },
        getTopicCompletionObject: function(){
            var resultObj = {};
            var topicsHash = _module.topicsHash;
            for (var i in topicsHash) {
                if (YAHOO.lang.hasOwnProperty(topicsHash, i)) {
                    resultObj[topicsHash[i].id] = topicsHash[i].isComplete();
                }
            }
			return resultObj;
        },
		getCurrentTopicId: function(){
			return _currentTopic.id;
		},
		getCurrentTopicsSubtopicIds: function(){
			return _currentTopic.subTopicIds;
		},
		isTopicComplete: function(topicId){
			return _module.getTopicById(topicId).isComplete();
		},
		calcIfModuleCompletionRequirementMet: function(){
			return _module.calcIfCompletionRequirementMet();
		},
		generateCompletionCode: function(){
			return String(FLN.Utils.getRandomString(9)) + "1";
		},
		getCompletionCode: function(){
			return _completionCode;
		}
    };
}();
FLN.FramesetController.init();
