import md5 from './md5'

/**
 * 是否启用cocos的api
 */
let enabelCC = true

let _global = typeof window === 'undefined' ? global : window;


let translate = { dx : 0, dy : 0 };
let eventMap = {};
let ccEventMap = {};
let displayMap = {};

/**
 * 对外接口
 */
module.exports = {
    // 基础UI
    showLoading,
    hideLoading,
    showTip,
    showSuccessTip,
    showErrorTip,

    // 网络相关
    get,
    post,

    // 小游戏独特UI
    drawImage,
    hideImage,
    updateImage,
    // download,

    cc : _global.cc,
    wx : _global.wx,
    setCanvasTranslate,
    getCanvas,
    getCanvasCtx,
    setDebug,

    //本地存储
    getStorage,
    setStorage,

    //签名构造
    encodePwd
}

Object.defineProperty(module.exports, "host", { 
    get: function() { 
        if (this.debug) {
            return 'https://test-xyxbox.duowan.com/'
        } else {
            return 'https://xyxbox.duowan.com/'
        }
    } 
}); 

function setDebug(debug) {
    module.exports.debug = debug
}

function getCanvas() {
    return _global.canvas || cc.game.canvas
}

function getCanvasCtx() {
    let gameCanvas = getCanvas()
    return gameCanvas.getContext('2d')
}

/**
 * 设置canvas的原点
 * @param {int} dx The distance to translate in X
 * @param {int} dy The distance to translate in Y
 */
function setCanvasTranslate(dx, dy) {
    translate.dx = dx;
    translate.dy = dy;
}

function drawImage(name, src, x, y, callback, options) {
    // 图片地址补齐http
    if (src.indexOf('http') !== 0) {
        src += 'http:'
    }

    // 微信里面只能用https的图片
    if (_global.wx) {
        src = src.replace(/http\:\/\//, 'https://')
    }

    if (enabelCC && _global.cc) {
        download(src, function(texture2D) {
            let pNode = options['pNode']
            let node = pNode.getChildByName(name)
            let sp = null
            let btn = null
            // 判断是否加过这个node了
            if (!node) {
                node = new cc.Node(name)
                node.zIndex = options['zIndex'] || 66666
                sp = node.addComponent(cc.Sprite)
                btn = node.addComponent(cc.Button)

                // node.x = x
                // node.y = y
                var widget = node.addComponent(cc.Widget)
                widget.isAlignTop = true
                widget.isAlignLeft = true
                widget.left = x
                widget.top = y
                node.parent = pNode
            } else {
                sp = node.getComponent(cc.Sprite)
                btn = node.getComponent(cc.Button)
                if (ccEventMap[name]) {
                    btn.node.off(cc.Node.EventType.TOUCH_START, ccEventMap[name])
                    delete ccEventMap[name]
                }
            }
            
            // 如果是多张图的情况
            if (options['num'] && options['num'] > 1) {
                options['texture2D'] = texture2D;
                displayMap[name] = [sp, x, y, options]
                if (!sp.spriteFrame) {
                    updateImage();
                }
            } else {
                sp.spriteFrame = new cc.SpriteFrame(texture2D);
            }

            if (callback) {
                ccEventMap[name] = callback
                btn.node.on(cc.Node.EventType.TOUCH_START, callback)
            }            
        });
    } else {
        let ctx = getCanvasCtx()
        if (!ctx) {
            console.log('目前不支持WebGL引擎渲染')
            return
        }

        let image = _global.wx ? wx.createImage() : new Image;
        image.onload = function () {
            displayMap[name] = [image, x, y, options]
            // updateImage()
            // 绑定事件
            if (callback) {
                _bindEvent(name, 'touchstart', image, x, y, options, callback)
            }
        }
        image.src = src
    }
}

let i = 0;
function updateImage() {
    let ctx = null;
    for (var name in displayMap) {
        let value = displayMap[name]
        let image = value[0]
        let options = value[3]
        let texture2D = options.texture2D;
        let orginSize = texture2D || image;

        let info = null;
        if (options && options['num'] && options['num'] > 1) {
            let cur = options['cur'] || 0;
            let curFrame  = options['curFrame'] || 0;
            let num = options['num']
            let interval = options['interval']

            if (++curFrame == interval) {
                curFrame = 0;
                cur = (cur + 1) % num;
            }
            
            let rows = options['rows'] || 1
            let cols = options['cols'] || 1
            let cur_rows = parseInt(cur / cols);
            let cur_cols = cur - cur_rows * cols;
            
            let img_width = orginSize.width / cols
            let img_height = orginSize.height / rows
            info = [img_width * cur_cols, img_height * cur_rows, img_width, img_height]

            // 设置显示列表
            displayMap[name][3]['curFrame'] = curFrame;
            displayMap[name][3]['cur'] = cur;
        } else {
            info = [value[1], value[2], orginSize.width, orginSize.height]
        }

        if (texture2D) {
            let sf = new cc.SpriteFrame(texture2D)
            sf.setRect(new cc.Rect(info[0], info[1], info[2], info[3]))
            image.spriteFrame = sf
        } else {
            let x = value[1] - translate.dx
            let y = value[2] - translate.dy
            ctx = ctx || getCanvasCtx();
            ctx.drawImage(image, info[0], info[1], info[2], info[3], x, y, info[2], info[3])
        }
    }
}

function hideImage(name, pNode = null) {
    _unbindEvent(name);
    if (displayMap[name]) {
        delete displayMap[name]
    }

    if (pNode) {
        let child = pNode.getChildByName(name)
        if (child) {
            child.removeFromParent(true)
        }
    }
}

function _unbindEvent(name) {
    eventMap[name] = eventMap[name] || {}
    for (let eventType in eventMap[name]) {
        _unbindOneEvent(name, eventType)
    }
}

function _unbindOneEvent(name, eventType) {
    eventMap[name] = eventMap[name] || {}
    if (eventMap[name][eventType]) {
        getCanvas().removeEventListener(eventType, eventMap[name][eventType])
        delete eventMap[name][eventType]
    }
}

// jquery offset原生实现
function _offset(target) {
    var top = 0,
        left = 0

    while(target.offsetParent) {
        top += target.offsetTop
        left += target.offsetLeft
        target = target.offsetParent
    }

    return {
        top: top,
        left: left,
    }
}

function _bindEvent(name, eventType, image, x, y, options, callback) {
    eventMap[name] = eventMap[name] || {}
    if (eventMap[name][eventType]) {
        _unbindOneEvent(name, eventType);
    }

    eventMap[name][eventType] = function(event) {
    　　 var _x, _y;
        var touches = event.touches;
        if (touches) {
            var canvas = getCanvas();
            let offset = _offset(canvas);
            _x = touches[0].clientX - offset.left,
            _y = touches[0].clientY - offset.top;
        } else if (event.layerX || event.layerX == 0) {
        　　 _x = event.layerX;
        　　 _y = event.layerY;
    　　 } else if (event.offsetX || event.offsetX == 0) { // Opera
         　　_x = event.offsetX;
         　　_y = event.offsetY;
    　　 }
         _checkRange(_x, _y, options)
    };

    function _checkRange(_x, _y, options) {
        let radio = _global.wx ?  0.67 : 1.5;
        let rows = options['rows'] || 1
        let cols = options['cols'] || 1
        let flag = _x > x && _x < x + image.width * radio / cols
        flag &= _y > y && _y < y + image.height * radio / rows
        if (flag && !self.isHide) { 
            callback && callback();
        }
    }

    getCanvas().addEventListener(eventType, eventMap[name][eventType]);
}

function download(src, callback) {
    if (enabelCC && _global.cc) {
        cc.loader.load(src, function (err, tex) {
            if (err) {
                cc.error(err);
            } else {
                callback(tex);
            }
        });
    } 
    else {
        wx.downloadFile({
          url: src,
          header: {},
          filePath: '',
          success: function (ret) {
              callback(ret.tempFilePath);
          }
        })
    }
}


// --------------  通用UI ----------------
let loadingTimeoutHandler = 0
function showLoading(title, timeout, cancelable) {
    let option = { title }
    if (!cancelable) {
        option['mask'] = true
    }

    if (_global.wx) {
        wx.showLoading(option)
    } else {
        console.log(`showLoading, title:${title}, timeout:${timeout}, cancelable:${cancelable}`)
    }
    
    // 超时时间为15s
    timeout = timeout || 15000;
    loadingTimeoutHandler = setTimeout(function(){
        hideLoading()
        showTip("加载超时，请稍后再试")
    }, timeout);
}

function hideLoading() {
    loadingTimeoutHandler && clearTimeout(loadingTimeoutHandler);
    loadingTimeoutHandler = 0;
    if (_global.wx) {
        wx.hideLoading()
    } else {
        console.log(`hideLoading`)
    }
}

function showSuccessTip(title, timeout) {
    showTip(title, timeout, {
        'icon' : 'success'
    });
}

function showErrorTip(title, timeout) {
    showTip(title, timeout, {
        'icon' : 'loading'
    });
}

function showTip(title, timeout, option) {
    option = option || {}
    option['title'] = title
    option['duration'] = timeout || 3000

    if (_global.wx) {
        wx.showToast(option)
    } else {
        console.log(`showTip:${title}, ${timeout}`)
    }
}

// --------------  网络相关接口 ------------
function _get(url, data, callback) {
    if (_global.wx) {
        wx.request({
            method:'GET',
            url: url,  
            data: data,
            dataType: 'text',
            success: function(ret) {
                callback(ret.data)
            }
        });
    } else {
        let query = _buildData(data);
        if (url.indexOf('?') >= 0) {
            url += '&' + query;
        } else {
            url += '?' + query;
        }

        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4 && (xhr.status >= 200 && xhr.status < 400)) {
                var text = xhr.responseText;
                callback(text);
            }
        };
        xhr.open("GET", url, true);
        xhr.send();
    }
}

function _post(url, data, callback) {
    if (_global.wx) {
        wx.request({
            method:'POST',
            url: url,  
            data: data,
            dataType: 'text',
            header: {
                //设置参数内容类型为x-www-form-urlencoded
                'content-type':'application/x-www-form-urlencoded',
            },
            success: function(ret) {
                callback(ret.data)
            }
        });
    } else {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4 && (xhr.status >= 200 && xhr.status < 400)) {
                var text = xhr.responseText;
                callback(text);
            }
        };
        xhr.open("POST", url, true);
        xhr.send(_buildData(data));
    }
}

function _buildData(data) {
    let query = '';
    for (let key in data) {
        query += key + '=' + data[key] + '&';
    }

    if (query) {
        query = query.substr(0, query.length - 1);
    }

    return query;
}

function get(url, data, callback, option) {
    option = option || {};

    // 支持post(url, callback)的写法;
    if (typeof data === 'function') {
        option = callback || {};
        callback = data;
        data = {};
    }

    option['loading'] && showLoading();
    _get(url, data, function(text) {
        option['loading'] && hideLoading();
        if (option['type'] === 'text' && typeof text == 'string') {
            callback && callback(text);
        } else {
            var objResult = _getAjaxResult(text);
            callback && callback(objResult);
        }
    });
}

/**
 * option object {'cache', 'loading', 'onTimeout'}
 * cache为true、every、once
 */
function post(url, data, callback, option) {
    option = option || {};
    // 支持postCross(url, callback)的写法;
    if ( typeof data == 'function') {
        option = callback || {};
        callback = data;
        data = {};
    }

    data['_from'] = 'ajax';
    //获取cache的key
    if (option['cache'] && window.localStorage) {
        var cacheKey = 'ajaxCache-' + url + '?' + $.param(data);
        //如果有cache则不出现loading
        var isCached = _loadAjaxCache(cacheKey, callback);
        if (isCached) {
            option['loading'] = false;
            if (option['cache'] == "must") {
                return;
            }
        }
    }

    if (option['loading']) {
        showLoading();
    }

    _post(url, data, function (text) {
        option['loading'] && hideLoading();
        if (option['type'] === 'text') {
            callback(text);
        } else {
            var objResult = _getAjaxResult(text);
            if (objResult['result'] && option['cache']) {
                var cache = getStorage(cacheKey);
                if (cache && cache == text) {
                    // 网络返回跟缓存一致
                    return;
                } else {
                    setStorage(cacheKey, xhr.responseText);
                }
            }

            _handleResult(callback, objResult);
        }
    });
}

function _getAjaxResult(text) {
    var objResult = {};
    var objError = {
        result : 0,
        msg : "系统繁忙，请稍后再试！"
    };

    try {
        objResult = JSON.parse(text);
        if (typeof objResult !== 'object' || objResult === null) {
            objResult = objError;
        }
    } catch (ex) {
        //非json的处理
        objResult = objError;
    }

    return objResult;
}

function _loadAjaxCache(cacheKey, callback) {
    var cache = getStorage(cacheKey); 
    if (cache) {
        var objResult = JSON.parse(cache);
        objResult._fromCache = true;
        _handleResult(callback, objResult);

        return true;
    } else {
        return false;
    }
}

function _handleResult(callback, objResult) {
    //session_id失效，重新验证登录
    if(!objResult.result && objResult.code === -5) {
        openLogin();
    } else {
        callback && callback(objResult);
    }
}


function getStorage(key) {
    if(_global.wx) {
        return wx.getStorageSync(key)
    }else {
        let str = localStorage.getItem(key)
        let data
        try{
            data = JSON.parse(str)
        } catch(e) {
            data = str
        }   
        
        return data
    }
}


function setStorage(key,value) {
    if(_global.wx) {
        wx.setStorage({
            key,
            data: value
        });
    }else {
        let str 
        try {
            str = JSON.stringify(value)
        } catch (error) {
            str = value
        }
        localStorage.setItem(key,str)
    }
}

function encodePwd(random, pwd) {
    var k1 = md5.sha1(random);
    var k2 = md5.sha1(k1);

    var v = md5.xor(md5.xor(pwd, k2), k1);
    return md5.base64encode(v);
}