var zxy = require('zxy-comm');
var path = require('path');
var _ = require('underscore');
var Promise = require('bluebird');
var multiparty = require('multiparty');
var fs = require('fs');
var setting = require('../../../setting.js');
var nodexml = require("node-xml");
var xml2js = require('xml2js');
var jsSHA = require('jssha');

//微信公众平台认证
// signature 微信加密签名，signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
// echostr 随机字符串
// timestamp 时间戳
// nonce 随机数
function validateToken(signature, echostr, timestamp, nonce) {
    var oriArray = new Array();
    oriArray[0] = nonce;
    oriArray[1] = timestamp;
    oriArray[2] = setting.wechat.token;
    oriArray.sort();
    var original = oriArray[0] + oriArray[1] + oriArray[2];
    var scyptoString = zxy.app.m_cryptogram.sha1(original);
    if (signature == scyptoString) {
        return echostr;
    }
    else {
        return "Bad Token!";
    }
}
exports.validateToken = validateToken;

//判断推送消息是否来自微信
// req 请求对象
function messageAvailability(req) {
    var oriArray = new Array();
    oriArray[0] = req.query.nonce;
    oriArray[1] = req.query.timestamp;
    oriArray[2] = setting.wechat.token;
    oriArray.sort();
    var original = oriArray[0] + oriArray[1] + oriArray[2];
    var scyptoString = zxy.app.m_cryptogram.sha1(original);
    if (req.query.signature == scyptoString) {
        return true;
    }
    else {
        return false;
    }
}
exports.messageAvailability = messageAvailability;

//获取AccessToken
var getAccessToken = function (callback) {
    zxy.app.m_redis.get(setting.wechat.accountid + ":accesstoken", function (accesstoken) {
        if (accesstoken) {
            callback(accesstoken);
        }
        else {
            zxy.app.m_request.getRequest("https", "api.weixin.qq.com", "443", "/cgi-bin/token?grant_type=client_credential&appid="
                + setting.wechat.appid + "&secret=" + setting.wechat.appsecret, "", null, null, function (d) {
                    d = JSON.parse(d);
                    if (d && d.access_token) {
                        zxy.app.m_redis.set(setting.wechat.accountid + ":accesstoken", d.access_token, (2 * 60 - 5) * 60);
                        callback(d.access_token);
                    }
                    else {
                        getAccessToken(callback);
                    }
                });
        }
    });
}
exports.getAccessToken = getAccessToken;

//获取JsSDKTicket
var getJsSDKTicket = function (callback) {
    zxy.app.m_redis.get(setting.wechat.accountid + ":jsSDKTicket", function (ticket) {
        if (ticket) {
            callback(ticket);
        }
        else {
            getAccessToken(function (token) {
                zxy.app.m_request.getRequest("https", "api.weixin.qq.com", "443", "/cgi-bin/ticket/getticket?access_token=" + token
                    + "&type=jsapi", "", null, null, function (d) {
                        d = JSON.parse(d);
                        if (d && d.ticket) {
                            zxy.app.m_redis.set(setting.wechat.accountid + ":jsSDKTicket", d.ticket, (2 * 60 - 5) * 60);
                            callback(d.ticket);
                        }
                        else {
                            getJsSDKTicket(callback);
                        }
                    });
            });
        }
    });
}
exports.getJsSDKTicket = getJsSDKTicket;

//Oauth2.0 根据Code获取微信信息 snsapi_base方式
//url https://open.weixin.qq.com/connect/oauth2/authorize?appid=&redirect_uri=&response_type=code&scope=snsapi_base&state=#wechat_redirect
var getWechatUserInfoBySnsapiBase = function (code, callback) {
    if (!callback) {
        callback = function (user) { }
    }
    zxy.app.m_request.getRequest("https", "api.weixin.qq.com", "443", "/sns/oauth2/access_token?appid="
        + setting.wechat.appid + "&secret=" + setting.wechat.appsecret + "&code=" + code + "&grant_type=authorization_code", "", null, null, function (wechat) {
            if (wechat && typeof (wechat) == "string") {
                wechat = JSON.parse(wechat);
            }
            var openid = wechat.openid;
            if (openid) {
                getAccessToken(function (accesstoken) {
                    if (accesstoken) {
                        zxy.app.m_request.getRequest("https", "api.weixin.qq.com", "443", "/cgi-bin/user/info?access_token="
                            + accesstoken + "&openid=" + openid + "&lang=zh_CN", "", null, null, function (cuser) {
                                callback(cuser);
                            });
                    }
                    else {
                        callback({ openid: openid });
                    }
                });
            }
            else {
                callback([]);
            }
        });
}
exports.getWechatUserInfoBySnsapiBase = getWechatUserInfoBySnsapiBase;

//解析器
var wechatXmlToJson = function (xml, callback) {
    var msg = {};
    xml2js.parseString(xml, function (err, result) {
        var data = result.xml;
        msg.ToUserName = data.ToUserName && data.ToUserName[0] ? data.ToUserName[0] : "";
        msg.FromUserName = data.FromUserName && data.FromUserName[0] ? data.FromUserName[0] : "";
        msg.CreateTime = data.CreateTime && data.CreateTime[0] ? data.CreateTime[0] : "";
        msg.MsgType = data.MsgType && data.MsgType[0] ? data.MsgType[0] : "";
        msg.Content = data.Content && data.Content[0] ? data.Content[0] : "";
        msg.MsgId = data.MsgId && data.MsgId[0] ? data.MsgId[0] : "";
        msg.PicUrl = data.PicUrl && data.PicUrl[0] ? data.PicUrl[0] : "";
        msg.MediaId = data.MediaId && data.MediaId[0] ? data.MediaId[0] : "";
        msg.Format = data.Format && data.Format[0] ? data.Format[0] : "";
        msg.ThumbMediaId = data.ThumbMediaId && data.ThumbMediaId[0] ? data.ThumbMediaId[0] : "";
        msg.Location_X = data.Location_X && data.Location_X[0] ? data.Location_X[0] : "";
        msg.Location_Y = data.Location_Y && data.Location_Y[0] ? data.Location_Y[0] : "";
        msg.Scale = data.Scale && data.Scale[0] ? data.Scale[0] : "";
        msg.Label = data.Label && data.Label[0] ? data.Label[0] : "";
        msg.Title = data.Title && data.Title[0] ? data.Title[0] : "";
        msg.Description = data.Description && data.Description[0] ? data.Description[0] : "";
        msg.Url = data.Url && data.Url[0] ? data.Url[0] : "";
        msg.Event = data.Event && data.Event[0] ? data.Event[0] : "";
        msg.EventKey = data.EventKey && data.EventKey[0] ? data.EventKey[0] : "";
        msg.Ticket = data.Ticket && data.Ticket[0] ? data.Ticket[0] : "";
        msg.Latitude = data.Latitude && data.Latitude[0] ? data.Latitude[0] : "";
        msg.Longitude = data.Longitude && data.Longitude[0] ? data.Longitude[0] : "";
        msg.Precision = data.Precision && data.Precision[0] ? data.Precision[0] : "";
        msg.Recognition = data.Recognition && data.Recognition[0] ? data.Recognition[0] : "";
        callback(msg);
    });
}
exports.wechatXmlToJson = wechatXmlToJson;


//处理业务逻辑
var processingBusiness = function (json, res) {
    //是否需要响应
    var respone = true;
    //开发者微信号
    var ToUserName = json.ToUserName ? json.ToUserName : "";
    //发送方帐号（一个OpenID）
    var FromUserName = json.FromUserName ? json.FromUserName : "";
    //消息创建时间 （整型）
    var CreateTime = json.CreateTime ? json.CreateTime : "";
    //消息类型
    var Event = "";
    //事件KEY值
    // subscribe：qrscene_为前缀，后面为二维码的参数值 只有当扫描二维码才有此参数
    // SCAN：是一个32位无符号整数，即创建二维码时的二维码scene_id 只有当扫描二维码才有此参数
    // CLICK：事件KEY值，与自定义菜单接口中KEY值对应
    // VIEW：事件KEY值，设置的跳转URL
    var EventKey = json.EventKey ? json.EventKey : "";
    //二维码的ticket，可用来换取二维码图片 只有当扫描二维码才有此参数
    var Ticket = json.Ticket ? json.Ticket : "";
    //地理位置维度
    var Latitude = json.Latitude ? json.Latitude : "";
    //地理位置经度
    var Longitude = json.Longitude ? json.Longitude : "";
    //地理位置精度
    var Precision = json.Precision ? json.Precision : "";
    //文本消息内容
    var Content = json.Content ? json.Content : "";
    //消息ID
    var MsgId = json.MsgId ? json.MsgId : "";
    //图片连接
    var PicUrl = json.PicUrl ? json.PicUrl : "";
    //媒体id 可以调用多媒体文件下载接口拉取数据。
    var MediaId = json.MediaId ? json.MediaId : "";
    //语音格式，如amr，speex等
    var Format = json.Format ? json.Format : "";
    //视频消息缩略图的媒体id，可以调用多媒体文件下载接口拉取数据。
    var ThumbMediaId = json.ThumbMediaId ? json.ThumbMediaId : "";
    //地理位置维度
    var Location_X = json.Location_X ? json.Location_X : "";
    //地理位置经度
    var Location_Y = json.Location_Y ? json.Location_Y : "";
    //地图缩放大小
    var Scale = json.Scale ? json.Scale : "";
    //地理位置信息
    var Label = json.Label ? json.Label : "";
    //消息标题
    var Title = json.Title ? json.Title : "";
    //消息描述
    var Description = json.Description ? json.Description : "";
    //消息链接
    var Url = json.Url ? json.Url : "";
    //语音识别结果
    var Recognition = json.Recognition ? json.Recognition : "";
    if (json.MsgType.toLowerCase() == "event") {
        switch (json.Event.toLowerCase()) {
            //订阅（包括搜索和扫描二维码）
            case "subscribe":
                if (EventKey) {
                    Event = "订阅（扫描二维码）";
                }
                else {
                    Event = "订阅（搜索公众号）";
                }
                break;
            //取消订阅
            case "unsubscribe":
                Event = "取消订阅";
                /*//修改用户的关注字段
                $wechatDAO.unSubscribe(FromUserName);*/
                break;
            //已关注的情况下扫描二维码
            case "scan":
                Event = "扫描二维码（已关注）";

                break;
            //上报地理位置
            case "location":
                Event = "上报地理位置";
                /*//修改用户的所在位置
                $wechatDAO.updateUserLocation(json);*/
                break;
            //自定义菜单
            case "click":
                Event = "自定义菜单";
                /*click(FromUserName, EventKey);*/
                break;
            //点击菜单跳转链接
            case "view":
                Event = "点击菜单跳转链接";

                break;
        }
    }
    else {
        //普通消息
        switch (json.MsgType.toLowerCase()) {
            //文本消息
            case "text":
                Event = "文本消息";
                break;
            //图片
            case "image":
                Event = "图片消息";
                break;
            //语音消息
            case "voice":
                Event = "语音消息";
                break;
            //视频消息
            case "video":
                Event = "视频消息";
                break;
            //小视频消息
            case "shortvideo":
                Event = "小视频消息";
                break;
            //地理位置消息
            case "location":
                Event = "地理位置消息";
                break;
            //链接消息
            case "link":
                Event = "链接消息";
                break;
        }
    }
    //响应微信，防止多次请求 回复客户端可使用客服接口
    if (respone) {
        res.send("");
    }
}
exports.processingBusiness = processingBusiness;

//被动回复消息
//res 响应对象
//ToUserName 接收方帐号（收到的OpenID）
//FromUserName 开发者微信号
//Content 回复的消息内容（换行：在content中能够换行，微信客户端就支持换行显示）
//Articles 多条图文消息信息，默认第一个为大图,注意，如果图文数超过10，则将会无响应  数据格式为json数组
//          示例：[{Title:"图文消息标题",Description:"图文消息描述",PicUrl:"图片链接，支持JPG、PNG格式，较好的效果为大图360*200，小图200*200",Url:"点击图文消息跳转链接"},...]
var replyWechat = function (res, ToUserName, FromUserName, Content, Articles) {
    var xml = "<xml><ToUserName><![CDATA[" + ToUserName + "]]></ToUserName><FromUserName><![CDATA[" + FromUserName + "]]></FromUserName><CreateTime>" + (new Date().getTime())
        + "</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[" + Content + "]]></Content></xml>";
    if (Articles != undefined && Articles != null && typeof (Articles) == "object" && Articles.length > 0) {
        var xml = "<xml><ToUserName><![CDATA[" + ToUserName + "]]></ToUserName><FromUserName><![CDATA[" + FromUserName + "]]></FromUserName><CreateTime>" + (new Date().getTime())
            + "</CreateTime><MsgType><![CDATA[news]]></MsgType><ArticleCount>" + Articles.length.toString() + "</ArticleCount><Articles>";
        var item = "";
        for (var i = 0; i < Articles.length; i++) {
            item += "<item><Title><![CDATA[" + (Articles[i].Title ? Articles[i].Title : "") + "]]></Title><Description><![CDATA[" + (Articles[i].Description ? Articles[i].Description : "")
                + "]]></Description><PicUrl><![CDATA[" + (Articles[i].PicUrl ? Articles[i].PicUrl : "") + "]]></PicUrl><Url><![CDATA[" + (Articles[i].Url ? Articles[i].Url : "") + "]]></Url></item>";
        }
        xml += item + "</Articles></xml>";
    }
    res.send(xml);
}
exports.replyWechat = replyWechat;

//发送客服文本消息
var sendTextMessage = function (openid, message) {
    getAccessToken(function (token) {
        var data = {
            touser: openid,
            msgtype: "text",
            text:
            {
                content: message
            }
        };
        zxy.app.m_request.postRequest("https", "api.weixin.qq.com", "443", "/cgi-bin/message/custom/send?access_token="
            + token, data, { 'Content-Length': new Buffer(JSON.stringify(data)).length }, null, function (result) { console.log(result); });
    });
}
exports.sendTextMessage = sendTextMessage;

//发送客服图片消息
var sendImageMessage = function (openid, mediaid) {
    getAccessToken(function (token) {
        var data = {
            touser: openid,
            msgtype: "image",
            image:
            {
                "media_id": mediaid
            }
        };
        zxy.app.m_request.postRequest("https", "api.weixin.qq.com", "443", "/cgi-bin/message/custom/send?access_token="
            + token, data, { 'Content-Length': new Buffer(JSON.stringify(data)).length }, null, function (result) { });
    });
}
exports.sendImageMessage = sendImageMessage;

//发送客服语音消息
var sendVoiceMessage = function (openid, mediaid) {
    getAccessToken(function (token) {
        var data = {
            touser: openid,
            msgtype: "voice",
            voice:
            {
                "media_id": mediaid
            }
        };
        zxy.app.m_request.postRequest("https", "api.weixin.qq.com", "443", "/cgi-bin/message/custom/send?access_token="
            + token, data, { 'Content-Length': new Buffer(JSON.stringify(data)).length }, null, function (result) { });
    });
}
exports.sendVoiceMessage = sendVoiceMessage;

//发送客服视频消息
//thumb_media_id 缩略图的媒体ID
//title 图文消息/视频消息/音乐消息的标题
//description 图文消息/视频消息/音乐消息的描述
var sendVideoMessage = function (openid, media_id, thumb_media_id, title, description) {
    getAccessToken(function (token) {
        var data = {
            touser: openid,
            msgtype: "video",
            video:
            {
                media_id: media_id,
                thumb_media_id: thumb_media_id,
                title: title,
                description: description
            }
        };
        zxy.app.m_request.postRequest("https", "api.weixin.qq.com", "443", "/cgi-bin/message/custom/send?access_token="
            + token, data, { 'Content-Length': new Buffer(JSON.stringify(data)).length }, null, function (result) { });
    });
}
exports.sendVideoMessage = sendVideoMessage;

//发送客服音乐消息
//title 图文消息/视频消息/音乐消息的标题
//description 图文消息/视频消息/音乐消息的描述
//musicurl 音乐链接
//hqmusicurl 高品质音乐链接，wifi环境优先使用该链接播放音乐
//thumb_media_id 缩略图的媒体ID
var sendMusicMessage = function (openid, title, description, musicurl, hqmusicurl, thumb_media_id) {
    getAccessToken(function (token) {
        var data = {
            touser: openid,
            msgtype: "music",
            music:
            {
                title: title,
                description: description,
                musicurl: musicurl,
                hqmusicurl: hqmusicurl,
                thumb_media_id: thumb_media_id
            }
        };
        zxy.app.m_request.postRequest("https", "api.weixin.qq.com", "443", "/cgi-bin/message/custom/send?access_token="
            + token, data, { 'Content-Length': new Buffer(JSON.stringify(data)).length }, null, function (result) { });
    });
}
exports.sendMusicMessage = sendMusicMessage;

//发送客服图文消息
//Articles 多条图文消息信息，默认第一个为大图,注意，如果图文数超过10，则将会无响应  数据格式为json数组
//          示例：[{title:"图文消息标题",description:"图文消息描述",picurl:"图片链接，支持JPG、PNG格式，较好的效果为大图360*200，小图200*200",url:"点击图文消息跳转链接"},...]
var sendNewsMessage = function (openid, Articles) {
    getAccessToken(function (token) {
        var data = {
            touser: openid,
            msgtype: "news",
            news:
            {
                articles: Articles
            }
        };
        zxy.app.m_request.postRequest("https", "api.weixin.qq.com", "443", "/cgi-bin/message/custom/send?access_token="
            + token, data, { 'Content-Length': new Buffer(JSON.stringify(data)).length }, null, function (result) { });
    });
}
exports.sendNewsMessage = sendNewsMessage;

//发送模版消息
//templateid 模版ID
//openid 接收人
//url 点击跳转的地址
//data 一个JSON格式的替换项 如 {"UserName":"周先生"}
var sendTemplateMessage = function (templateid, openid, url, data) {
    getAccessToken(function (token) {
        var p_data = {};
        for (var key in data) {
            p_data[key] = {
                "value": data[key],
                "color": "#696969"
            };
        }
        var params = {
            "touser": openid,
            "template_id": templateid,
            "url": url,
            "topcolor": "#FF0000",
            "data": p_data
        };
		var len = new Buffer(JSON.stringify(params)).length;
        zxy.app.m_request.postRequest("https", "api.weixin.qq.com", "443", "/cgi-bin/message/template/send?access_token=" + token,params,{'Content-Length':len});
    });
}
exports.sendTemplateMessage = sendTemplateMessage;

//获取用户信息
var getUserInfo = function (openid, callback) {
    getAccessToken(function (token) {
        //https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
        zxy.app.m_request.getRequest("https", "api.weixin.qq.com", "443", "/cgi-bin/user/info?access_token=" + token + "&openid="
            + openid + "&lang=zh_CN", null, null, null, function (json) {
                json = JSON.parse(json);
                if (json && json.subscribe && json.subscribe.toString() == "1") {
                    callback(json);
                }
                else {
                    callback(undefined);
                }
            });
    });
}
exports.getUserInfo = getUserInfo;

//获取openid Oauth2.0网页授权
var getopenid = function (code, callback) {
    zxy.app.m_request.getRequest("https", "api.weixin.qq.com", "443", "/sns/oauth2/access_token?appid="
        + setting.wechat.appid + "&secret=" + setting.wechat.appsecret + "&code=" + code
        + "&grant_type=authorization_code", null, null, null, function (json) {
            //console.log(json);
            json = JSON.parse(json);
            if (json && json.openid) {
                callback(json.openid);
            }
            else {
                callback(undefined);
            }
        });
}
exports.getopenid = getopenid;

// //创建自定义菜单
// var createMenu = function (data, callback) {
//     getAccessToken(function (token) {
//         zxy.app.m_request.postRequest("https", "api.weixin.qq.com", "443", "/cgi-bin/menu/create?access_token="
//             + token, data, null, null, function (json) {
//                 json = JSON.parse(json);
//                 if (json && json.errcode == 0) {
//                     $wechatDAO.saveMenu(JSON.stringify(data));
//                     callback(true);
//                 }
//                 else {
//                     callback(false);
//                 }
//             });
//     });
// }
// exports.createMenu = createMenu;

var jssdksign = function (req, callback) {
    getJsSDKTicket(function (ticket) {
        var opts = {
            "debug": false,
            "appid": setting.wechat.appid,
            "timestamp": parseInt(new Date().getTime() / 1000) + '',
            "nonceStr": Math.random().toString(36).substr(2, 15),
            "signature": null
        };
        var ret = {
            "jsapi_ticket": ticket,
            "nonceStr": opts.nonceStr,
            "timestamp": opts.timestamp,
            "url": req.query.url
            // "url": decodeURIComponent(req.query.url)
        };
        var shaObj = new jsSHA("SHA-1", 'TEXT');
        shaObj.update(_raw(ret));
        opts.signature = shaObj.getHash("HEX");
        console.log(ret, opts);
        callback(opts);
    });
}
exports.jssdksign = jssdksign;

var _raw = function (args) {
    var keys = Object.keys(args);
    keys = keys.sort();
    var newArgs = {};
    keys.forEach(function (key) {
        newArgs[key.toLowerCase()] = args[key];
    });
    var string = '';
    for (var k in newArgs) {
        string += '&' + k + '=' + newArgs[k];
    }
    string = string.substr(1);
    return string;
};

//订阅
var subscribe = function (message) {
    getUserInfo(message.FromUserName, function (user) {
        if (user) {
            var sql = "INSERT INTO zxy_wechat_fans("
                + "id,subscribe,openid,nickname,sex,province,city,country,headimgurl,privilege,`language`,subscribe_time,unionid,remark,groupid,"
                + "ext,location,createtime)VALUES(UUID(),"
                + "@subscribe,@openid,@nickname,@sex,@province,@city,@country,@headimgurl,'',@language,@subtime,@unionid,@remark,@groupid,'','',NOW());";
            zxy.app.m_mysql.query(sql, {
                subscribe: user && user.subscribe ? user.subscribe : '1',
                openid: user && user.openid ? user.openid : '',
                nickname: user && user.nickname ? user.nickname : '',
                sex: user && user.sex ? user.sex : '1',
                language: user && user.language ? user.language : '',
                city: user && user.city ? user.city : '',
                province: user && user.province ? user.province : '',
                country: user && user.country ? user.country : '',
                headimgurl: user && user.headimgurl ? user.headimgurl : '',
                subtime: user && user.subscribe_time ? user.subscribe_time : '',
                unionid: user && user.unionid ? user.unionid : '',
                remark: user && user.remark ? user.remark : '',
                groupid: user && user.groupid ? user.groupid : '0'
            });
        }
    });
}
exports.subscribe = subscribe;

//取消订阅
var unsubscribe = function (message) {
    zxy.app.m_mysql.query("UPDATE zxy_wechat_fans SET subscribe = '0' WHERE openid = @openid", {
        openid: message.FromUserName
    });
}
exports.unsubscribe = unsubscribe;

//上报地理位置
var location = function (message) {
    getUserInfo(message.FromUserName, function (user) {
        var location = {
            Latitude: message && message.Latitude ? message.Latitude : '',
            Longitude: message && message.Longitude ? message.Longitude : '',
            Precision: message && message.Precision ? message.Precision : ''
        };
        var data = {
            openid: message.FromUserName,
            location: JSON.stringify(location)
        };
        if (user) {
            data.subscribe = user && user.subscribe ? user.subscribe : '1';
            data.openid = user && user.openid ? user.openid : data.openid;
            data.nickname = user && user.nickname ? user.nickname : '';
            data.sex = user && user.sex ? user.sex : '1';
            data.language = user && user.language ? user.language : '';
            data.city = user && user.city ? user.city : '';
            data.province = user && user.province ? user.province : '';
            data.country = user && user.country ? user.country : '';
            data.headimgurl = user && user.headimgurl ? user.headimgurl : '';
            data.subtime = user && user.subscribe_time ? user.subscribe_time : '';
            data.unionid = user && user.unionid ? user.unionid : '';
            data.remark = user && user.remark ? user.remark : '';
            data.groupid = user && user.groupid ? user.groupid : '0';
            var sql = "UPDATE zxy_wechat_fans SET nickname = @nickname,sex = @sex, province = @province,city = @city,country = @country,headimgurl = @headimgurl,`language` = @language,subscribe_time = @subtime,unionid = @unionid,remark = @remark,groupid = @groupid,location = @location WHERE openid = @openid";
            zxy.app.m_mysql.query(sql, data);
        }
        else {
            zxy.app.m_mysql.query("UPDATE zxy_wechat_fans SET location = @location WHERE openid = @openid", data);
        }
    });
}
exports.location = location;