/**
 * http://nadoby.ru
 * Survey engine for partner sites
 * 2010-09-13 Version: 0.0.6
 * 
 * @dependents  json2.js (for browsers do not support JSON) - http://www.JSON.org/json2.js
 *              easyXDM - http://easyxdm.net/ 
 * 
 * @example var questions = new Survey();
 *          questions.render(function onReady(){});
 *
 * @name Survey
 * @param Object    settings    hash with options, described below.
 *                      wrapper - DOM element or ID that the survey should be inserted into. Required.
 *                      id - survey ID. Required.
 *                      autoResize - If true auto adjust survey height. Default: true.
 *                      positon - Specifies where the survey should be displayed. Possible values: 
 *                                  1) a single string representing position within viewport: 'center', 'left', 'right', 'top', 'bottom'. 
 *                                  2) an array containing an x,y coordinate pair in pixel offset from left, top corner of viewport (e.g. [350,100]) 
 *                                  3) an array containing x,y position string values (e.g. ['right','top'] for top right corner).
 *                                  Default: ['center', 'center']
 *                      attributes - Additional properties that should be applied. 
 *                                   This can also contain style objects e.g: {style:{width:'100px', height:'100px'}}.
 *                                   Default: {style:{width:'630px', height:'540px'}}
 *                      onCancel - Function that should be called when user refused fill and close survey. 
 *                      onSuccess - Function that should be called when survey completed fill. 
 *                      onDestroy - Function that should be called when survey destruction and remove DOM node.   
 *                      onError(exception) - Function that should be called when survey throw error. Possible exceptions:
 *                                              1) Survey not found       
 * @return Survey
 * 
 * 
 * @name render - Display survey
 * @param function onReady - Function that should be called when the survey is ready. Optional.
 * 
 * 
 * @name destroy - The destruction of the survey object. Call onDestroy action;
 * @param void
 * 
 * @name height - Set survey height, make sense if only autoResize set false. Get actual survey height.
 * @param value
 * @return actual survey height
 */
function Survey(kind, options){

//    constant
    var HELPWIDTH = 250;

    kind = kind || 1;
    function _pageSize(){
        var xScroll, yScroll;
        if (window.innerHeight && window.scrollMaxY) {
            xScroll = window.innerWidth + window.scrollMaxX;
            yScroll = window.innerHeight + window.scrollMaxY;
        }
        else 
            if (document.body.scrollHeight > document.body.offsetHeight) { // all but Explorer Mac
                xScroll = document.body.scrollWidth;
                yScroll = document.body.scrollHeight;
            }
            else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
                xScroll = document.body.offsetWidth;
                yScroll = document.body.offsetHeight;
            }
        var windowWidth, windowHeight;
        if (self.innerHeight) { // all except Explorer
            windowWidth = document.documentElement.clientWidth
                ? document.documentElement.clientWidth
                : self.innerWidth; 
            windowHeight = self.innerHeight;
        }
        else 
            if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
                windowWidth = document.documentElement.clientWidth;
                windowHeight = document.documentElement.clientHeight;
            }
            else 
                if (document.body) { // other Explorers
                    windowWidth = document.body.clientWidth;
                    windowHeight = document.body.clientHeight;
                }
        
        var pageWidth = xScroll < windowWidth ? xScroll : windowWidth;
        var pageHeight = yScroll < windowHeight ? windowHeight : yScroll;  
        
        switch (_browser()) {
            case 'msie':
            case 'opera':
                var bodyStyle = document.body.currentStyle;
                pageWidth += parseInt(bodyStyle.marginLeft) + parseInt(bodyStyle.marginRight);
                pageHeight += parseInt(bodyStyle.marginTop) + parseInt(bodyStyle.marginBottom);
                break;
        }
        return [pageWidth,pageHeight, windowWidth, windowHeight];
    }

    
    function _browser(){

        var agent = navigator.userAgent.toLowerCase();
        var browser = /opera/.exec(agent) || /msie/.exec(agent) || /webkit/.exec(agent) ||
                    !/compatible/.test(agent) && /mozilla/.exec(agent); 
                
        return browser[0] || '';
    }
    
    function _scroll() {
        
        return typeof window.pageYOffset  === 'number'
            ? {y: window.pageYOffset, x: window.pageXOffset}
            : document.body && (document.body.scrollLeft || document.body.scrollTop)
                ? {y: document.body.scrollTop, x: document.body.scrollLeft}
                : document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)
                    ? {y: document.documentElement.scrollTop, x: document.documentElement.scrollLeft}
                    : {y: 0, x: 0};
    }    
    
    function _position(element){
    
        var box;
        if (typeof element.getBoundingClientRect === 'function') {
            var body = document.body,
                docElem = document.documentElement;
            box = element.getBoundingClientRect();
            var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop,
                scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft,
                clientTop = docElem.clientTop || body.clientTop || 0,
                clientLeft = docElem.clientLeft || body.clientLeft || 0;
                
            box = {top: Math.round(box.top +  scrollTop - clientTop), left:Math.round(box.left + scrollLeft - clientLeft)}; 
        }
        else {
            box = {top: 0, left: 0};
            while (element) {
                box.top += parseInt(element.offsetTop);
                box.left += parseInt(element.offsetLeft);
                element = element.offsetParent;
            }
        }
        
        return box;
    }

    var containerName;
    function _surveyContainer(){
    
        var frame = document.getElementById(containerName);
        if (!frame) 
            throw Error("Survey container can't be empty");
        return frame;
    }
    
    function _request(options){

        var params = ['salt=' + (new Date).valueOf().toString() + Math.round(Math.random() * 17).toString(),
            'kind=' + kind, 'withoutThank=' + (options.withoutThank ? 1 : 0),
            'withoutCancel=' + (options.withoutCancel ? 1 : 0), 'withoutSubtitle=' + (options.withoutSubtitle ? 1 : 0)];
        if (options.source) params.push('source=' + options.source);    
        if (options.place) params.push('place=' + options.place);
        if (options.parent) params.push('parent=1');
        
        if (options['default']) params.push ('default=' + options['default']); 
        if (options.ids) {
            if (!(options.ids instanceof Array)) options.ids = [options.ids];
            params.push('ids=' + options.ids.join());
        }
        if (options.categories) {
            if (!(options.categories instanceof Array)) options.categories = [options.categories];
            params.push('categories=' + options.categories.join());
        }

        return 'http://nadoby.ru/survey/widget?' + encodeURI(params.join('&')); 
    }
    
//    constant    
    var SCROOLDELTA = 13;
    function _scrollBy(needY){

        var offset = _scroll().y - needY;
        var delta = offset > 0 ? -SCROOLDELTA : SCROOLDELTA;
        var scrollBy = function(){
            offset -= SCROOLDELTA;
            if (offset > 0) {
                window.scrollBy(0, delta);
                window.setTimeout(scrollBy, 1);
            }
        };
        offset = Math.abs(offset);        
        scrollBy();
    }
    
    function _containerPosition(options){

        var box = {},
            page = _pageSize();
            
        if (!(options.position instanceof Array)) options.position = [options.position, options.position];
        switch (typeof options.position[0] == typeof options.position[1] ? typeof options.position[0] : undefined) {
            case 'string':
                var parentPos;
                if (options.parent && options.position[0].match(/^near/)) {
                    parentPos = _position(options.parent);
                    box.top = (options.position[0] === 'nearBottom' 
                        ? parentPos.top + parseInt(options.parent.height) + 15 
                        : parentPos.top);
                }
                else {
                    box.top = Math.round(options.position[0] === 'bottom' 
                        ? page[3] - attributes.height 
                        : (options.position[0] === 'top' ? 0 : page[3] / 2 - attributes.height / 2));
                }
        
                if (options.parent && options.position[1].match(/^near/)) {                    
                    parentPos = parentPos || _position(options.parent);
//                    600 = 550(default survey width) + 50(margin)
                    box.left = (options.position[1] === 'nearLeft'
                        ? parentPos.left - 600
                        : (options.position[1] == 'nearBelow' ? parentPos.left : parentPos.left + parseInt(options.parent.width) + 15)
                    );
                }
                else {
//                    275 = 550/2 (550 - standart survey width)
                    box.left = Math.round(options.position[1] === 'right' 
                        ? page[2] - attributes.width 
                        : (options.position[1] === 'left' ? 0 : page[2] / 2 - 275));
                }
                break;
            case 'number':
                box.top = options.position[0];
                box.left = options.position[1];
                break;
            default:
                box.top = Math.round(page[3] / 2 - attributes.height / 2);
                box.left = Math.round(page[2] / 2 - 275);
        }
        return box;
    }
    
    
    options.autoResize = typeof options.autoResize === 'boolean' ? options.autoResize : true;
    options.autoScroll = typeof options.autoScroll === 'boolean' ? options.autoScroll : false; 
    options.withoutThank = typeof options.withoutThank === 'boolean' ? options.withoutThank : false;
    options.withoutCancel = typeof options.withoutCancel === 'boolean' ? options.withoutCancel : false;
    options.withoutSubtitle = typeof options.withoutSubtitle === 'boolean' ? options.withoutSubtitle : false;
    
    var attributes = options.attributes || {};
    attributes.height = attributes.height || 0;
    attributes.width = attributes.width || 0;
    delete attributes.id;   
    attributes.style = attributes.style || {};
//    z-index: 46574 - not a magic XXX    
    attributes.style.zIndex = 46574;
    
    var rpc, overlay, wrapper, 
        pageInterval, actualHeight = undefined,
        oldKeyDown, easyClose = true;
    return {
        height: function (h){

            if (typeof h === 'number') {
                try {
                    var c = _surveyContainer();
                    c.height = c.style.height = h + 'px';
                } 
                catch (e) {
                }
            }
            return actualHeight;
        },
        destroy: function(){
            if (typeof options.onDestroy === 'function') 
                options.onDestroy.apply(window, []);
            rpc.destroy();
            try {
                if (overlay) wrapper.removeChild(overlay);
                if (pageInterval) window.clearInterval(pageInterval);
            } 
            catch (e) {
            };
            if (oldKeyDown)
                document.onkeydown = oldKeyDow;
        },
        render: function(onReady){
            try {
                _surveyContainer();
            } 
            catch (e) {
                var help, $this = this;
                wrapper = options.position
                    ? document.body
                    : (typeof options.wrapper === 'string' ? document.getElementById(options.wrapper) : options.wrapper); 
                attributes.name = containerName = 'iframe-survey-' + (new Date).valueOf().toString() + Math.round(Math.random() * 5).toString();
                rpc = new easyXDM.Rpc({
                    container: wrapper,
                    remote: _request(options),
                    onReady: function () {
                        var size = Survey.SIZE[kind],
                            container = _surveyContainer();

                        if (options.position) {
                            var cp = _containerPosition(options);
                            container.style.top = cp.top + 'px';
                            container.style.left = cp.left + 'px';
                            container.style.position = 'absolute';
                        }
                        
                        container.width = container.style.width = size[0] + 'px';
                        container.height = container.style.height = size[1] + 'px';
                                                
                        function internalOnReady () {

                            if (overlay) {
                               overlay.onclick = function(){
                                    if (easyClose) $this.destroy();
                                    return true;
                                }
                                oldKeyDow = document.onkeydown;
                                document.onkeydown = function(e){
                                    if (!e) e = window.event;
                                    if (easyClose && e.keyCode == 27) $this.destroy();
                                    return true;
                                }
                            }
                            
                            if (kind == Survey.DIRECT) {
                                if (options['default']) rpc.setDefaultValue(options['default']);
                                rpc.onSurveyReady();
                            }
                            if (typeof onReady === 'function') 
                                onReady();
                        }

                        if (options.parent || options.autoScroll) {
                            var scrollBySurvey = window.setInterval(function(){
                                if (actualHeight != undefined) {
                                    window.clearInterval(scrollBySurvey);
                                    var containerPos = _position(container), scroll = _scroll();
                                    var parentPos = options.parent ? _position(options.parent) : containerPos; 

                                    var B = containerPos.top + parseInt(container.style.height) - (_pageSize()[3] + scroll.y);
                                    if (B > 0) {
                                        _scrollBy(parentPos.top - scroll.y > B ? scroll.y + B + 10 : parentPos.top - 10);
                                    }
                                    else 
                                        if (scroll.y > containerPos.top) {
                                            _scrollBy(parentPos.top - 15);
                                        }
                                    
                                    internalOnReady();
                                }
                            }, 900);
                        }
                        else {
                            internalOnReady();
                        }                        
                    },
                    props: attributes
                }, {
                    local: {
                        withoutThank: function () {
                            return options.withoutThank;
                        },
                        // surveys - surveys quantity
                        onHelp: function (action, surveys) {                            
                            switch (action) {
                                case 'show':
                                    var container = _surveyContainer();
                                    var containerPos = _position(container);
                                    if (!help) {
                                        help = document.createElement('div');
                                        help.innerHTML = surveys > 1 
                                          ? '\u041d\u0435\u0020\u0442\u0440\u0430\u0442\u044c\u0442\u0435\u0020\u0432\u0440\u0435\u043c\u044f\u0020\u043d\u0430\u0020\u043f\u043e\u0438\u0441\u043a\u0438\u0020\u0432\u0020\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435\u002c\u0020\u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435\u0020\u0432\u0020\u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u043c\u0020\u0441\u043f\u0438\u0441\u043a\u0435\u0020\u0442\u043e\u002c\u0020\u0447\u0442\u043e\u0020\u0412\u044b\u0020\u0438\u0449\u0435\u0442\u0435\u002c\u0020\u043e\u0442\u0432\u0435\u0442\u044c\u0442\u0435\u0020\u043d\u0430\u0020\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e\u0020\u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432\u0020\u2014\u0020\u0438\u0020\u043d\u0430\u0448\u0438\u0020\u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u044b\u0020\u043d\u0430\u0439\u0434\u0443\u0442\u0020\u0432\u0441\u0435\u0020\u0437\u0430\u0020\u0412\u0430\u0441\u0020\u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e\u0020\u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u002e'
                                          : '\u041d\u0435\u0020\u0442\u0440\u0430\u0442\u044c\u0442\u0435\u0020\u0432\u0440\u0435\u043c\u044f\u0020\u043d\u0430\u0020\u043f\u043e\u0438\u0441\u043a\u0438\u0020\u0432\u0020\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435\u002c\u0020\u043e\u0442\u0432\u0435\u0442\u044c\u0442\u0435\u0020\u043d\u0430\u0020\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e\u0020\u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432\u0020\u2014\u0020\u0438\u0020\u043d\u0430\u0448\u0438\u0020\u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u044b\u0020\u043d\u0430\u0439\u0434\u0443\u0442\u0020\u0432\u0441\u0435\u0020\u0437\u0430\u0020\u0412\u0430\u0441\u0020\u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e\u0020\u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u002e';
                                        document.body.appendChild(help);
                                        help.style.cssText = "border: 1px solid #A4ABB3; background: #FFFFFF url('http://nadoby.ru/i/b-help-bg.png') no-repeat;" 
                                            + "display: none; font-family: Verdana; font-size: 11px; line-height: 1.5em;" 
                                            + "padding: 10px; z-index: 46532; position: absolute; left: 0; width:230px; top:" + (containerPos.top + 21) + 'px'; 
                                    }
                                    if (help) {
                                        var windowWidth = _pageSize()[2];
                                        containerPos.right = containerPos.left + parseInt(container.width) - 12;
                                        if (windowWidth - containerPos.right < HELPWIDTH) containerPos.right = windowWidth - HELPWIDTH - 9;
                                        if (containerPos.right < 0) containerPos.right = containerPos.left + 7; 
                                        help.style.left = containerPos.right + 'px'; 
                                        help.style.display = 'block';
                                    }
                                    break;
                                case 'hide':
                                    if (help) help.style.display = 'none';
                                    break;                                    
                            }
                            
                            return true;
                        },
                        onFillSurvey: {
                            method: function(additional){
                                if (additional.ids) {
                                    var question = options;
                                    question.wrapper = options.wrapper;
                                    question.position = question.popup && question.popup.position ? question.popup.position : ['nearBottom', 'nearBelow'];
                                    question.overlay = true;
                                    question.ids = additional.ids;
                                    question.parent = _surveyContainer();
                                    delete question.categories;
                                    var onDestroy = question.onDestroy;
                                    question.onDestroy = function(){
                                        rpc.onDirectDestroy();
                                        if (typeof onDestroy === 'function') 
                                            onDestroy();
                                    };
                                    var onError = question.onError;
                                    question.onError = function(){
                                        rpc.onDirectDestroy();
                                        if (typeof onError === 'function') 
                                            onError();
                                    };
                                    var directSurvey = new Survey(Survey.DIRECT, question);
                                    directSurvey.render();
                                }
                                return true;
                            }
                        },
                        onError: {
                            method: function(exception){
                                
                                if (exception instanceof Object 
                                    && typeof options.onError === 'function') {
                                        options.onError.apply(window, [Error(exception.message)]);
                                }
                                rpc.destroy();
                                try {
                                    if (options.overlay && overlay) {
                                        wrapper.removeChild(overlay);
                                        window.clearInterval(pageInterval);
                                    }
                                } 
                                catch (e) {
                                };
                                return true;
                            }
                        },
                        changeHeight: {
                            method: function(height){
                                if (height) {
                                    actualHeight = parseInt(height);
                                    if (options.autoResize) {
                                        try {
                                            _surveyContainer().style.height = actualHeight + 'px';
                                        } 
                                        catch (e) {
                                        }
                                    }
                                }
                                return true;
                            }
                        },
                        onSuccess: {
                            method: function(){
                                if (typeof options.onSuccess === 'function') 
                                    options.onSuccess.apply(window, []);
                                return true;
                            }
                        },
                        onCancel: {
                            method: function(){
                                if (typeof options.onCancel === 'function') 
                                    options.onCancel.apply(window, []);
                                return true;
                            }
                        },
                        onChangeStep: {
                            method: function(step){
                                switch (step) {
                                    case 1:
                                    case 3:
                                        easyClose = true;
                                        break;
                                    case 2:
                                        easyClose = false;
                                        break;
                                }
                            }
                        },
                        onDestroy: {
                            method: function(){
                                if (typeof options.onDestroy === 'function') 
                                    options.onDestroy.apply(window, []);
                                rpc.destroy();
                                try {
                                    if (options.overlay && overlay) {
                                        wrapper.removeChild(overlay);
                                        window.clearInterval(pageInterval);
                                    }
                                } 
                                catch (e) {
                                };
                                if (oldKeyDown)
                                    document.onkeydown = oldKeyDow;
                                return true;
                            }
                        }
                    },
                    remote: {
                        onDirectDestroy: {},
                        onSurveyReady: {},
                        setDefaultValue: {}
                    }
                });
                
                if (options.overlay) {
                    var page = _pageSize();
                    overlay = document.createElement('div');
                    wrapper.appendChild(overlay);
                    overlay.style.cssText = 'margin:0 !important;padding:0 !important;border:0 !important;width:' + page[0]  + 'px; height:' + page[1] + 'px;' +
                        'position:absolute; z-index:46532; left:0;top:0;' +                         
                        (_browser() == 'msie' 
                            ? 'background-color:#000; filter: progid:DXImageTransform.Microsoft.Alpha(opacity=75);' 
                            : 'background:url(http://nadoby.ru/i/black-px.png);');

                    pageInterval = window.setInterval(function() {
                        page = _pageSize();
                        overlay.style.width = page[0] + 'px';
                        overlay.style.height = page[1] + 'px';
                    }, 1000);
                }
            }
        }
    }
}

Survey.DIRECT = 1;
Survey.BANNER200X300 = 2;
Survey.BANNER150X300 = 3;
Survey.BANNER468X60 = 4;
Survey.BANNER728X90 = 5;
Survey.BANNER240X350 = 6;
Survey.BANNER240X400 = 7;

Survey.SIZE = {
    1: [564, 0],
    2: [200, 300],
    3: [150, 300],
    4: [468, 60],
    5: [728, 90],
    6: [240, 350],
    7: [240, 400] 
};

Survey.Common = {
    prequel: function() {
        var params = document.location.search.replace(/^\?/, '').split('&'), prequel = {};
        for (var i in params) {
            if (decodeURIComponent(params[i]).match(/^n6s6_([^=]+)=(.+)$/)) 
                prequel[RegExp.$1] = RegExp.$2;
        }
        return prequel;
    }
}

