CourseManager.prototype.scorm_init = function() {
    var _that = this;

    switch (scorm) {
        case 'dscorm':
            _that.scorm_getData();
            break;

        case 'scorm':
            _that.scormPipwerks = pipwerks.SCORM;

            var lmsConnected = _that.scormPipwerks.init();

            if (lmsConnected) {
                debug.log("LMS connected!");

                switch (_that.scormPipwerks.get("cmi.core.lesson_status")) {
                    case 'completed':
                    case 'passed':
                        _that.course.user.courseStatus = "c"
                        break;

                    case 'failed':
                        _that.course.user.courseStatus = "f";
                        break;

                    case 'incomplete':
                    default:
                        _that.course.user.courseStatus = "nc";
                        break;

                }

                var scormLessonLocation = parseInt(_that.scormPipwerks.get("cmi.core.lesson_location"));
                if (isNaN(scormLessonLocation)) {
                    scormLessonLocation = 0;
                }

                _that.course.user.lesson_location = scormLessonLocation;

                _that.scorm_loadSuspendData(_that.scormPipwerks.get("cmi.suspend_data"));

            } else {
                debug.log("Cant connect to LMS!!!!");
            }

            break;

        case 'none':
            break;
    }
};

CourseManager.prototype.scorm_save = function() {
    var _that = this;

    switch (scorm) {
        case 'dscorm':
            _that.scorm_setData();
            break;

        case 'scorm':
            debug.log('saving scorm, lesson status: ' + _that.course.user.courseStatus + ", points: " + _that.course.user.score + ", req: " + _that.course.opts.score.required + ", max: " + _that.course.opts.score.max + ", lesson loc: " +  _that.course.user.lesson_location);
            var scorm2004_lesson_status;
            var scorm_lesson_status;
            switch (_that.course.user.courseStatus) {
                case 'c':
                    scorm_lesson_status = "passed";
                    scorm2004_lesson_status = "completed";
                    // if (!_that.course.opts.req.s) {
                    //     _that.course.user.score = _that.course.opts.score.required;
                    // }
                    break;

                case 'f':
                    scorm2004_lesson_status = "browsed";
                    scorm_lesson_status = "failed";
                    break;

                case 'nc':
                default:
                    scorm_lesson_status = "incomplete";
                    scorm2004_lesson_status = "incomplete";
                    break;

            }

            if (_that.scormPipwerks.version === "2004") {
                _that.scormPipwerks.set("cmi.success_status",  scorm2004_lesson_status);
                _that.scormPipwerks.set("cmi.completion_status",  scorm2004_lesson_status);
            }

            _that.scormPipwerks.set("cmi.core.lesson_status",  scorm_lesson_status);
            _that.scormPipwerks.set("cmi.core.score.min", 0);
            _that.scormPipwerks.set("cmi.core.score.max", _that.course.opts.score.max);

            var percentage_score;
            if (_that.course.opts.score.required === 0) {
                percentage_score = 100;
            } else {
                percentage_score = parseInt((_that.course.user.score / _that.course.opts.score.required) * 100);
            }

            if(percentage_score > 100)
                percentage_score = 100;
            if(percentage_score <= 0)
                percentage_score = 0;

            var scorm_score_raw;
            if (_that.course.opts.score.max === 0) {
                scorm_score_raw = 100;
            } else {
                scorm_score_raw = parseInt((_that.course.user.score / _that.course.opts.score.max) * 100);
            }

            if(scorm_score_raw > 100)
                scorm_score_raw = 100;
            if(scorm_score_raw <= 0)
                scorm_score_raw = 0;
            

            _that.scormPipwerks.set("cmi.core.score.raw", scorm_score_raw);
            _that.scormPipwerks.set("cmi.score.scaled", percentage_score);

            _that.scormPipwerks.set("cmi.core.lesson_location", _that.course.user.lesson_location);

            _that.scormPipwerks.set("cmi.suspend_data", _that.scorm_saveSuspendData());

            _that.scormPipwerks.save();
            break;

        case 'none':
            break;
    }
};

CourseManager.prototype.scorm_quit = function() {
    var _that = this;

    if (isObject(_that.scormPipwerks)) {
        _that.scormPipwerks.quit();
    }
};

CourseManager.prototype.getURLParameters = function() {
    
    var url =  window.location.search.substring(0);
    
    var result = {};
                var searchIndex = url.indexOf("?");
                if (searchIndex == -1 ) return result;
    var sPageURL = url.substring(searchIndex +1);
    var sURLVariables = sPageURL.split('&');
    for (var i = 0; i < sURLVariables.length; i++)
    {       
        var sParameterName = sURLVariables[i].split('=');      
        result[sParameterName[0]] = sParameterName[1];
    }
    return result;
};

CourseManager.prototype.scorm_saveSuspendData = function() {
    var _that = this;

    var suspend_data_string = { };

    var user_codes = [ ];
    var objects_data = [ ];
    var pages_data = [ ];
    var draw_page_data = [ ];


    // save page completion status | save already not drawed pages
    for (var page in _that.course.pages) {
        if (_that.course.pages[page].opts.compl === 1) {
            if (pages_data.indexOf(page) === -1) {
                pages_data.push(parseInt(page));
            }
        }
        if (_that.course.pages[page].opts.notDrawed === true) {
            if (draw_page_data.indexOf(page) === -1) {
                draw_page_data.push(parseInt(page));
            }
        }
    }

    for (var o in _that.course.objs) {
        var splitted_object_id = _that.course.objs[o].id.split("-");

        // prepare user id array for shorter objects array
        var ob_id = splitted_object_id[0];
        if (user_codes.indexOf(ob_id) === -1) {
            user_codes.push(ob_id);
        }


        // prepare object that are already passed
        if(_that.course.objs[o].compl !== 0 || _that.course.objs[o].touched === 1) {

            // create object code field [0,9,2] => [user_id, object_number, page_id]
            var object_code = user_codes.indexOf(splitted_object_id[0]) + 
                                ',' + 
                                splitted_object_id[1] + 
                                "," + 
                                splitted_object_id[2] +
                                "," + 
                                _that.course.objs[o].compl;

            // if its a question - add field with attempts and user selection
            if (typeof _that.course.objs[o].question === "object") {
                // add attempts field
                object_code += "," + _that.course.objs[o].question.attempts;

                // object for user answers - needed for qtext question
                var  userAnswers = { };

                // add separator to easly split normal fields from user answers
                object_code += ",*^|";

                // add user selection fields
                for (var answer in _that.course.objs[o].question.answers) {

                    // MULTIPLE CHOICE QUIZ
                    var userSelectionArray = _that.course.objs[o].question.answers[answer].userSelection;
                    if (_that.getObjectType(_that.course.objs[o]) === "quiz_multiple") {
                        if (typeof userSelectionArray[userSelectionArray.length-1] === "boolean") {
                            userAnswers[answer.split("-")[2]] = userSelectionArray[userSelectionArray.length-1].toString().charAt(0);
                        }
                    }

                    // QTEXT
                    if (_that.getObjectType(_that.course.objs[o]) === "quiz_qtext") {

                        // object with answers
                        userAnswers[answer] = { };

                        // iterate through every subanswer and hold last user selection
                        for (var subanswer in _that.course.objs[o].question.answers[answer]) {
                            var subanswerUserSelectionArray = _that.course.objs[o].question.answers[answer][subanswer].userSelection;
                            userAnswers[answer][subanswer] = subanswerUserSelectionArray[subanswerUserSelectionArray.length-1];
                            if (typeof _that.course.objs[o].question.answers[answer][subanswer].userSelection !== 'undefined') {
                                _that.course.objs[o].compl = 1;
                            }
                        }
                        
                    }
                }

                object_code += JSON.stringify(userAnswers);
                
            }


            objects_data.push(object_code);


        }
    }



    suspend_data_string['uc'] = user_codes;
    suspend_data_string['o'] = objects_data;
    suspend_data_string['p'] = pages_data;
    suspend_data_string['dp'] = draw_page_data;
    suspend_data_string['s'] = _that.course.user.score;
    suspend_data_string['v'] = _that.course.opts.trigger;

    debug.log(JSON.stringify(suspend_data_string));
    return JSON.stringify(suspend_data_string);
};

CourseManager.prototype.scorm_loadSuspendData = function(data) {
    var _that = this;

    try {
       var suspend_data = JSON.parse(data);
       debug.log("******************* suspend_data *********************");
       debug.log(suspend_data);
       debug.log("****************************************");
    }
    catch(e) {
       debug.log('Saved course data seems to be corrupted. Could not load course progress.');
       debug.log(e);
       return;
    }


    // load page completion status
    try {

        for (var page in suspend_data.p) {
            if (typeof _that.course.pages[suspend_data.p[page]] === "object") {
                _that.course.pages[suspend_data.p[page]].opts.compl = 1;
            }
        }

        for (var page in suspend_data.dp) {
            if (typeof _that.course.pages[suspend_data.dp[page]] === "object") {
                _that.course.pages[suspend_data.dp[page]].opts.notDrawed = true;
                _that.course.opts.drawedFromScorm = true;
                var pageObjects = _that.getPageObjects(suspend_data.dp[page]);

                for (var pageOb = pageObjects.length - 1; pageOb >= 0; pageOb--) {
                    var pageObject = pageObjects[pageOb];
                    pageObject.notDrawed = true;
                    if (pageObject.status === 1 && pageObject.score > 0) {
                        _that.course.opts.score.max -= pageObject.score;
                    }
                };
                _that.course.opts.numberOfPages--;  
            }
        }

        var numberOfPages = Utils.ObjectLength(_that.course.pages);

        var properOrder = 0;

        for (var p = 0; p < numberOfPages; p++) {
            var pageData = _that.getPageByOrder(p);
            if (pageData.opts.notDrawed !== true) {
                pageData.opts.order = properOrder;
                properOrder++;
            } else {
                pageData.opts.order = -1;
            }
        }

    } catch(e) {
       debug.log('Pages data is corrupted.');
       debug.log(e);
    }

    // load user score
    try {
        if (!isNaN(parseInt(suspend_data.s))) {
            _that.course.user.score = parseInt(suspend_data.s);
        }
    } catch(e) {
       debug.log('Score data is corrupted.');
       debug.log(e);
    }

    // load variables
    try {

        var variables = suspend_data.v;

        debug.log(variables);

        _that.course.opts.trigger = variables;

    } catch(e) {
       debug.log('Variables data is corrupted.');
       debug.log(e);
    }


    // load objects status
    // try {

        for (var ob in suspend_data.o) {
            // split data - normal data | question data
            var ob_data = suspend_data.o[ob].split("*^|");

            // split normal data by ,
            var ob_main_vars = ob_data[0].split(",");

            // merge data to get object id
            var ob_id = suspend_data.uc[parseInt(ob_main_vars[0])] + "-" + ob_main_vars[1] + "-" + ob_main_vars[2];

            // get real object from course
            var real_ob = _that.getObjectByID(ob_id);

            if (typeof real_ob === "object") {
                var ob_completion_status = parseInt(ob_main_vars[3]);
                real_ob.compl = ob_completion_status;

                if (typeof real_ob.question === "object") {
                    var question_data = JSON.parse(ob_data[1]);

                    // load user attempts
                    real_ob.question.attempts = isNaN(parseInt(ob_main_vars[4])) ? ob_main_vars[4] : parseInt(ob_main_vars[4]);

                    real_ob.touched = 1;

                    if (_that.getObjectType(real_ob) === "quiz_multiple") {
                        if (ob_completion_status === 2) {
                            for (var ans in question_data) {
                                var true_or_false = (question_data[ans] === "t");
                                real_ob.question.answers["multiple-answer-" + ans].userSelection = [true_or_false];
                            }
                        }
                    }

                    if (_that.getObjectType(real_ob) === "quiz_qtext") {
                        for (var ans in question_data) {
                            for (var subans in question_data[ans]) {
                                real_ob.question.answers[ans][subans].userSelection.push(question_data[ans][subans]);
                            }
                        }
                    }
                }


            }
            
        }

    // } catch(e) {
    //    debug.log('Objects data is corrupted.');
    //    debug.log(e);
    // }

    debug.log("Course saved data loaded!");
};

CourseManager.prototype.scorm_setData = function() {
    var _that = this;

    var jsonCM = JSON.stringify(CM.course);
    var compressJsonCM = LZString.compressToBase64(jsonCM);

    var params = this.getURLParameters();

    var mailingHash = null;

    for (var paramName in params) {
        if (paramName == 'mh') {
            mailingHash = params[paramName];
        }
    }

    var request = {
        request: 11,
        pid: pid,
        uid: _that.course.user.login,
        courseStatus: CM.course.user.courseStatus,
        data: compressJsonCM,
        mailingHash: mailingHash
    }

    var ret = _that.scorm_ajaxRequest(request);
};

CourseManager.prototype.scorm_getData = function(data) {
    var _that = this;

    var params = this.getURLParameters();

    var mailingHash = null;

    for (var paramName in params) {
        if (paramName == 'mh') {
            mailingHash = params[paramName];
        }
    }

    var userHash = Utils.readCookie('userhash');

    if (userHash !== null) {
        _that.course.user.login = userHash;
    } else {
        var ra = Math.floor((Math.random() * 100000));
        var da = new Date().getTime();
        var str = ra.toString() + da.toString();
        var ha = CryptoJS.MD5(str).toString();

        _that.course.user.login = ha;
        Utils.createCookie('userhash', ha, 0);
    }


    var request = {
        request: 10,
        pid: pid,
        uid: _that.course.user.login,
        mailingHash: mailingHash
    };
    
    var ret = _that.scorm_ajaxRequest(request);

    var objCM = null;
    if (ret.data != null && ret.data != '') {
        // debug.log(ret.data);
        if (typeof ret.data === 'object') {
            // jesli obiekt to przypisz go pod objCM
            objCM = ret.data;
        } else {
            // jesli nie obiekt to dekompresuj
            var dec = LZString.decompressFromBase64(ret.data);
            objCM = JSON.parse(dec);
        }
    }

    // do usuniecia
    _that.course.user.page_time = { };
    for (var p in _that.course.pages) {
        _that.course.user.page_time[p] = 0;
    }
    // end

    if (typeof objCM === 'object' && objCM != null) {
        _that.scorm_updateData(objCM);
    } else {
        _that.course.user.login = ret.login;
    }
};

CourseManager.prototype.scorm_updateData = function(data) {
    var _that = this;

    // update CM.course.objs
    for (var p in data.objs) {
        if (typeof _that.course.objs[p] === 'object') {
            _that.course.objs[p].compl = data.objs[p].compl;

            // questions
            if (typeof _that.course.objs[p].question != 'undefined') {
                 _that.course.objs[p].question.attempts = data.objs[p].question.attempts;

                 if (_that.course.objs[p].action === 22) {
                    for (var i in _that.course.objs[p].question.answers) {
                        if (typeof _that.course.objs[p].question.answers[i] === 'object') {
                            _that.course.objs[p].question.answers[i].correct = data.objs[p].question.answers[i].correct;
                            _that.course.objs[p].question.answers[i].userSelection = data.objs[p].question.answers[i].userSelection;
                        }
                    }
                 }

                 if (_that.course.objs[p].action === 23) {
                    for (var i in _that.course.objs[p].question.answers) {
                        if (typeof _that.course.objs[p].question.answers[i] === 'object') {
                            for (var j in _that.course.objs[p].question.answers[i]) {
                                if (typeof _that.course.objs[p].question.answers[i] === 'object' && typeof data.objs[p].question.answers[i] === 'object') {
                                    _that.course.objs[p].question.answers[i][j].userSelection = data.objs[p].question.answers[i][j].userSelection;
                                        // ZADANIADOMEP =============================================
                                        // _that.course.objs[p].compl = 1;
                                        // ZADANIADOMEP END=============================================
                                }
                            }
                        }
                    }
                }
            }

            // forms
            if (typeof _that.course.objs[p].form !== 'undefined' &&
                (_that.course.objs[p].action === 50 ||
                _that.course.objs[p].action === 51 ||
                _that.course.objs[p].action === 52 ||
                _that.course.objs[p].action === 53 ||
                _that.course.objs[p].action === 54)) {
                _that.course.objs[p].form.answers = data.objs[p].form.answers;
            }
        }
    }

    // project variables update if exist
    for (var scormV = data.opts.trigger.length - 1; scormV >= 0; scormV--) {
        var varObjectFromScorm = data.opts.trigger[scormV];
        for (var courseV = _that.course.opts.trigger.length - 1; courseV >= 0; courseV--) {
            var varObjectInCourse = _that.course.opts.trigger[courseV];
            if (varObjectFromScorm.pvarname == varObjectInCourse.pvarname) {
                varObjectInCourse.pvarvalue = varObjectFromScorm.pvarvalue;
            }
        };
    };

    debug.log("USER DATA");
    debug.log(data.user);

    // update CM.course.user
    for (var o in data.user) {
        if (typeof _that.course.user[o] != 'undefined') {
            debug.log('updating.... : ' + o + " to: " + data.user[o]);
            _that.course.user[o] = data.user[o];
        }
    }

    // update CM.course.pages.opts.compl & update CM.course.pages.opts.notDrawed
    for (var page in data.pages) {
        if (typeof _that.course.pages[page] != 'undefined' && typeof data.pages[page] != "undefined") {
            _that.course.pages[page].opts.compl = data.pages[page].opts.compl;
    
            if (data.pages[page].opts.notDrawed === true) {
                _that.course.pages[page].opts.notDrawed = true;

                _that.course.opts.drawedFromScorm = true;

                var pageObjects = _that.getPageObjects(page);

                for (var pageOb = pageObjects.length - 1; pageOb >= 0; pageOb--) {
                    var pageObject = pageObjects[pageOb];
                    pageObject.notDrawed = true;
                    if (pageObject.status === 1 && pageObject.score > 0) {
                        _that.course.opts.score.max -= pageObject.score;
                    }
                };
                _that.course.opts.numberOfPages--;  
            }
        }
    }


    // reset page orders
    var numberOfPages = Utils.ObjectLength(_that.course.pages);

    var properOrder = 0;

    for (var p = 0; p < numberOfPages; p++) {
        var pageData = _that.getPageByOrder(p);
        if (pageData.opts.notDrawed !== true) {
            pageData.opts.order = properOrder;
            properOrder++;
        } else {
            pageData.opts.order = -1;
        }
    }
};

CourseManager.prototype.scorm_ajaxRequest = function(request, async, callback) {
    var request = JSON.stringify(request);
    var ret;
    var url;

    if (typeof async === 'undefined') {
        async = false;
    }

    // url = '../../../../../../assets/lms/scorm.php';
    url = '../../../assets/lms/scorm.php';

    // if (typeof loc === "string") {
    //     url = 'assets/lms/darkanscorm.php';
    // } else {
    //     url = '../../../assets/lms/darkanscorm.php';
    // }
    
    $.ajax({
        type: 'POST',
        url: url,
        async: async,
        data: {
            request: request
        },
        success: function(data) {
            ret = data;
            debug.log(data);
            debug.log(JSON.parse(data));

            if (typeof callback === 'function') {
                callback(JSON.parse(data));
            }
        },
        error: function(data){
            debug.log('--------------------- ERROR sm.js CourseManager.prototype.scormAjax ---------------------');
            debug.log(data);
            debug.log('-----------------------------------------------------------------------------------------');
        }
    });
    var return_data;
    if (typeof async === "undefined" || async === false) {
        try {
            return_data = JSON.parse(ret);
        } catch(e) {
            return_data = {'error': 'error parsing json'};
        }
    }

    return return_data;
};