;(function(win) {
    'use strict';
    win.qnPromotionQRCode = win.qnPromotionQRCode || {};
    // DOM事件兼容处理
    var Ev = {};
    if (win.addEventListener) {
        Ev.on = function(el, evType, handler) {
            el.addEventListener(evType, handler, false);
        };
    } else {
        Ev.on = function(el, evType, handler) {
            el.attachEvent('on' + evType, function() {
                handler.apply(el, arguments);
            });
        };
    }
    if (win.removeEventListener) {
        Ev.purge = function(el, evType) {
            el.removeEventListener(evType);
        };
    } else {
        Ev.purge = function(el, evType) {
            el.detachEvent('on' + evType);
        };
    }

    // 推广组件
    function Widget (cfg) {

        var scriptNode, scripts = document.getElementsByTagName('script');
        for (var i = 0; i < scripts.length; i++) {
            if ((/\/qn-promotion-qrcode\.js/gi).test(scripts[i].src)) {
                scriptNode = scripts[i];
                break;
            }
        }
        if (scriptNode.getAttribute('data-render') === 'manual' ) {return;} // 不自动实例化
        this._cfg = {
            renderTo: null, // {HTMLElement} 组件渲染到哪个节点
            uri: '', // {String} 用于生成二维码的url
            txt: '', // {String} 推广文案
            minWidth: 960
        };
        this._merge(this._cfg, cfg);

        this._assetsHost = '';
        this._rootNode = null;
        this._qrcodeInstance = null;
        this._winResizeTimeout = null;
        this._ie6ScrollTimeout = null;
        this._smsPanelTimeout = null;
        this._hintTimeout = null;
        this._sessionId = '';
        this._isFall = false; // 是否服务降级
    }

    Widget.prototype = {

        init: function() {
            this._initWidget();
        },

        _initWidget: function() {
            this._dom();
            this._qrcode();
            this._event();
            this._jsonpCallback();
            if (!('placeholder' in document.createElement('input'))) {this._placeholder();}
            if ((/msie 6/gi).test(navigator.userAgent)) {this._fixIE6();}
            this._onSmsHover();
        },

        // 环境检测: daily还是线上
        _detectEnv: function() {
            var scriptNode, scripts = document.getElementsByTagName('script');
            for (var i = 0; i < scripts.length; i++) {
                if ((/\/qn-promotion-qrcode\.js/gi).test(scripts[i].src)) {
                    scriptNode = scripts[i];
                    break;
                }
            }
            this._assetsHost = scriptNode.src.match(/^https?:\/\/(g\.assets\.daily\.taobao\.net|g\.tbcdn\.cn|g\.alicdn\.com)/i)[0];
        },

        MOBILE_NUM_ERROR: '请输入正确的手机号码！',
        VERIFY_CODE_ERROR: '请输入正确的验证码！',
        SEND_SMS_SUCCESS: '发送成功！',
        SEND_SMS_FAIL: '发送失败，请重试。',
        SEND_SMS_AFTER: '{{time}}秒后重新发送',
        FREE_SMS_INSTALL: '免费发送安装',

        _tmpl: '<div class="J_SMSPanel">' +
                    '<input type="text" class="J_MobileNum" placeholder="输入手机号" maxlength="11" />' +
                    '<input type="text" class="J_VerifyCode" placeholder="输入验证码" maxlength="4" />' +
                    '<button class="J_Setup">免费发送安装</button>' +
                    '<img style="display: none;" onload="this.style.display = \'block\'" src="" class="J_VerifyImg" width="100" height="30" />' +
                    '<a href="javascript:;" class="J_NewVerifyImg">换一张</a>' +
                    '<p class="J_Hint hint"></p>' +
                '</div><div class="qrwrap">' +
                    '<p class="slogan">{{txt}}</p>' +
                    '<div class="J_QRCode"></div>' +
                '</div>'
                ,

        _dom: function() {
            this._rootNode = document.createElement('div');
            this._rootNode.id = 'qn-promotion-widget';
            (this._cfg.renderTo || document.getElementsByTagName('body')[0]).appendChild(this._rootNode);
            this._rootNode.innerHTML = this._tmpl.replace(/\{\{txt\}\}/g, this._cfg.txt);
        },

        _qrcode: function() {
            var target = this._byClass('J_QRCode', 'div', this._rootNode)[0];
            this._qrcodeInstance = new qnPromotionQRCode.QRCode(target, {
                text: this._cfg.uri,
                width: 86,
                height: 86,
                colorDark : '#000000',
                colorLight : '#ffffff',
                correctLevel : qnPromotionQRCode.QRCode.CorrectLevel.Q
            });
        },

        _placeholder: function() {
            var mNum = this._byClass('J_MobileNum', 'input', this._rootNode)[0];
            var vCode = this._byClass('J_VerifyCode', 'input', this._rootNode)[0];
            mNum.value = mNum.getAttribute('placeholder');
            vCode.value = vCode.getAttribute('placeholder');
            Ev.on(mNum, 'focus', function(ev) {
                if (mNum.value === mNum.getAttribute('placeholder')) {mNum.value = '';}
            });
            Ev.on(mNum, 'blur', function(ev) {
                if (!mNum.value) {mNum.value = mNum.getAttribute('placeholder');}
            });
            Ev.on(vCode, 'focus', function(ev) {
                if (vCode.value === vCode.getAttribute('placeholder')) {vCode.value = '';}
            });
            Ev.on(vCode, 'blur', function(ev) {
                if (!vCode.value) {vCode.value = vCode.getAttribute('placeholder');}
            });
        },

        _fixIE6: function() {
            var _self = this;
            _self._rootNode.style.top = document.documentElement.scrollTop + 200 + 'px';
            Ev.on(win, 'scroll', function(ev) {
                clearTimeout(_self._ie6ScrollTimeout);
                _self._rootNode.style.display = 'none';
                _self._ie6ScrollTimeout = setTimeout(function() {
                    _self._rootNode.style.top = document.documentElement.scrollTop + 200 + 'px';
                    if (_self._winWidth() > _self._cfg.minWidth) {_self._rootNode.style.display = 'block';}
                }, 100);
            });
        },

        _event: function() {
            var _self = this;
            // Ev.on(win, 'resize', function(ev) {
            //     _self._rootNode.style.display = 'none';
            //     clearTimeout(_self._winResizeTimeout);
            //     _self._winResizeTimeout = setTimeout(function() {
            //         if (_self._winWidth() > _self._cfg.minWidth) {_self._rootNode.style.display = 'block';}
            //     }, 100);
            // });
            $('body').on('click', function(ev){
                var target = $(ev.target);
                if(target.hasClass('J_Setup')){
                    _self._onSendSmsClick();
                }
                if(target.hasClass('J_VerifyImg') || target.hasClass('J_NewVerifyImg')){
                    _self._verifyImg();
                }
            })
            // Ev.on(_self._rootNode, 'click', function(ev) {
            //     var target = _self._evTarget(ev);
            //     if (target.className === 'J_Close') {_self._close();}
            //     if (_self._hasClass(target, 'J_NewVerifyImg') || _self._hasClass(target, 'J_VerifyImg')) {_self._verifyImg();}
            //     if (_self._hasClass(target, 'J_Setup') && !target.disabled) {_self._onSendSmsClick();}
            // });
            // Ev.on(_self._rootNode, 'mouseover', function(ev) {
            //     if (_self._evTarget(ev).className === 'J_SMS') {_self._onSmsHover();}
            //     if (_self._hasClass(_self._evTarget(ev), 'J_SMSPanel')) {_self._onSmsPanelHover();}
            // });
            // Ev.on(_self._rootNode, 'mouseout', function(ev) {
            //     if (_self._evTarget(ev).className === 'J_SMS') {_self._delayHideSmsPanel();}
            //     if (_self._hasClass(_self._evTarget(ev), 'J_SMSPanel')) {_self._onSmsPanelOut(ev);}
            // });
            Ev.on(_self._byClass('J_MobileNum', 'input', _self._rootNode)[0], 'blur', function(ev) {
                _self._onMobileNumBlur();
            });
            Ev.on(_self._byClass('J_VerifyCode', 'input', _self._rootNode)[0], 'blur', function(ev) {
                _self._onVerifyCodeBlur();
            });
        },

        _close: function() {
            document.getElementsByTagName('body')[0].removeChild(this._rootNode);
        },

        _assetsMap: {
            css: {tag: 'link', uri: 'href', attr: {rel: 'stylesheet'}},
            js: {tag: 'script', uri: 'src', attr: {type: 'text/javascript'}}
        },

        _merge: function(o, other) {
            for (var key in other) {
                if (other.hasOwnProperty(key)) {o[key] = other[key];}
            }
        },

        _winWidth: function() {
            return document.documentElement.clientWidth;
        },

        _hasClass: function(el, cls) {
            return (new RegExp('(^|\\s)' + cls + '(\\s|$)')).test(el.className);
        },

        _byClass: function(cls, tag, root) {
            var els = (root || document).getElementsByTagName(tag || '*');
            var r = new RegExp('(^|\\s)' + cls + '(\\s|$)'), result = [];
            for (var i = 0; i < els.length; i++) {
                if (r.test(els[i].className)) {result[result.length] = els[i];}
            }
            return result.length ? result : null;
        },

        _onSmsHover: function() {
            // this._showSmsPanel();
            if (!this._sessionId && !this._isFall) {this._getSessionId();}
        },

        _showSmsPanel: function() {
            // clearTimeout(this._smsPanelTimeout);
            $('.J_SMSPanel').show();
        },

        _delayHideSmsPanel: function(delay) {
            var _self = this;
            clearTimeout(_self._smsPanelTimeout);
            _self._smsPanelTimeout = setTimeout(function() {
                _self._byClass('J_SMSPanel', 'div', this._rootNode)[0].style.display = 'none';
            }, delay || 500);
        },

        _onSmsPanelHover: function() {
            clearTimeout(this._smsPanelTimeout);
        },

        _onSmsPanelOut: function(ev) {
            var toEl = ev.relatedTarget || ev.toElement;
            if (this._isIn(toEl, this._byClass('J_SMSPanel', 'div', this._rootNode)[0])) {return;}
            this._delayHideSmsPanel();
        },

        _evTarget: function(ev) {
            ev = ev || win.event;
            return ev.target || ev.srcElement;
        },

        _isIn: function(inner, ancestor) {
            while(inner !== ancestor) {
                inner = inner.parentNode;
                if (!inner) {return false;}
            }
            return true;
        },

        _verifyImg: function() {
            $('.J_VerifyImg').attr('src', 'http://pin.aliyun.com/get_img?identity=jdy.tmall.com&sessionid=' + this._sessionId + '&t=' + (new Date()).getTime());
        },

        _jsonp: function(url, cache, params) {
            var query = [];
            if (!cache) {params.nocache = (new Date()).getTime();}
            for (var key in params) {
                if (params.hasOwnProperty(key)) {query.push(key + '=' + encodeURIComponent(params[key]));}
            }
            url = url + '?' + query.join('&');
            var js = document.createElement('script');
            js.type = 'text/javascript';
            document.getElementsByTagName('head')[0].appendChild(js);
            js.src = url;
        },

        _jsonpCallback: function() {
            var _self = this;
            win.jsonpQnQRCodeSessionId = function(data) {
                _self._getSessionIdSucc(data);
            };
            win.jsonpQnQRCodeSms = function(data) {
                _self._querySmsSendSucc(data);
            };
        },

        _getSessionId: function() {
            var host = (/\.daily\./).test(location.host) ? 'http://jdy.daily.tmall.net' : 'http://jdy.tmall.com';
            var url = host + '/marketing_validate';
            this._jsonp(url, true, {callback: 'jsonpQnQRCodeSessionId'});
        },

        _getSessionIdSucc: function(sid) {
            if (sid) {
                this._sessionId = sid;
                this._verifyImg();
                return;
            }
            // 服务降级
            this._isFall = true;
            $('.J_VerifyCode').hide();
            $('.J_VerifyImg').hide();
            $('.J_NewVerifyImg').hide();
        },

        _hint: function(type, msg, delay) {
            // var p = this._byClass('J_Hint', 'p', this._rootNode)[0];
            var p = $('.J_Hint')[0];
            p.innerHTML = msg;
            p.className = 'J_Hint hint ' + type;
            p.style.display = 'block';
            clearTimeout(this._hintTimeout);
            this._hintTimeout = setTimeout(function() {
                p.style.display = 'none';
                p.innerHTML = '';
                p.className = 'J_Hint hint';
            }, delay || 2000);
        },

        _onMobileNumBlur: function() {
            var mNum = this._byClass('J_MobileNum', 'input', this._rootNode)[0];
            var val = mNum.value, pHolder = mNum.getAttribute('placeholder');
            if (!val || val === pHolder || this._mobileNumValid()) {return;}
            this._hint('error', this.MOBILE_NUM_ERROR);
        },

        _onVerifyCodeBlur: function() {
            var vCode = this._byClass('J_VerifyCode', 'input', this._rootNode)[0];
            var val = vCode.value, pHolder = vCode.getAttribute('placeholder');
            if (!val || val === pHolder || this._verifyCodeValid()) {return;}
            this._hint('error', this.VERIFY_CODE_ERROR);
        },

        _onSendSmsClick: function() {
            if (!this._mobileNumValid()) {this._hint('error', this.MOBILE_NUM_ERROR); return;}
            if (!this._verifyCodeValid() && !this._isFall) {this._hint('error', this.VERIFY_CODE_ERROR); return;}
            var host = (/\.daily\./).test(location.host) ? 'http://jdy.daily.tmall.net' : 'http://jdy.tmall.com';
            this._jsonp(host + '/marketing_sms', false, {
                sessionId: this._sessionId,
                checkCode: $('.J_VerifyCode').val(),
                phone: $('.J_MobileNum').val(),
                url: 'http://work.taobao.com',
                callback: 'jsonpQnQRCodeSms'
            });
        },

        _querySmsSendSucc: function(data) {
            switch(data.code) {
                case 0: // 发送成功
                    this._sendSmsSuccess(data.time);
                    break;
                case 100: // 参数缺失
                case 200: // 参数不合法
                    this._hint('error', this.MOBILE_NUM_ERROR);
                    break;
                case 300: // 发送失败
                case 400: // 系统异常
                    this._hint('error', this.SEND_SMS_FAIL);
                    break;
                case 500: // 验证码失效
                    this._getSessionId();
                    this._hint('error', '验证码失效，请换一个。');
                    break;
                case 600: // 验证码错误
                    this._hint('error', '验证码错误，请重新输入。');
                    break;
                default:
                    this._hint('error', this.SEND_SMS_FAIL);
            }
        },

        _sendSmsSuccess: function(time) {
            var _self = this, btnSend = _self._byClass('J_Setup', 'button', _self._rootNode)[0];
            _self._hint('success', _self.SEND_SMS_SUCCESS);
            btnSend.disabled = true;
            btnSend.className = 'J_Setup send-sms-disable';
            var countDown = setInterval(function() {
                if (time > 0) {
                    btnSend.innerHTML = _self.SEND_SMS_AFTER.replace(/\{\{time\}\}/g, time--);
                    return;
                }
                clearInterval(countDown);
                btnSend.disabled = false;
                btnSend.className = 'J_Setup';
                btnSend.innerHTML = _self.FREE_SMS_INSTALL;
            }, 1000);
        },

        _mobileNumValid: function() {
            return (/[0-9]{11}/).test($('.J_MobileNum').val());
        },

        _verifyCodeValid: function() {
            return (/[0-9A-z]{4}/).test($('.J_VerifyCode').val());
        }
    };
    // export
    win.qnPromotionQRCode.Ev = Ev;
    win.qnPromotionQRCode.Widget = Widget;

    // Ev.on(win, 'load', function() {
    //     var scriptNode, scripts = document.getElementsByTagName('script');
    //     for (var i = 0; i < scripts.length; i++) {
    //         if ((/\/qn-promotion-qrcode\.js/gi).test(scripts[i].src)) {
    //             scriptNode = scripts[i];
    //             break;
    //         }
    //     }
    //     if (scriptNode.getAttribute('data-render') === 'manual' ) {return;} // 不自动实例化
    //     var cfg = {};
    //     cfg.uri = scriptNode.getAttribute('data-uri');
    //     cfg.txt = scriptNode.getAttribute('data-txt');
    //     cfg.renderTo = document.getElementsByTagName('body')[0];
    //     new Widget(cfg).init();
    // });
})(window);