const crypto = require('crypto');
const moment = require('moment');
const md5 = require('md5');
const sha1 = require('sha1');

function pad2(n) {
    return n < 10 ? '0' + n : n
}

/**
 * 微信指定的加密算法
 */
function encrypt(obj, addtionalStr) {
    // sort fields alphabetically 
    let keyArray = [];
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            keyArray.push(key);
        }
    }

    keyArray.sort((l, r) => {
        if (l > r) {
            return 1;
        } else if (l < r) {
            return -1;
        } else {
            throw new 'encrypted obj with same key: ' + l;
        }
    });

    let rawString = '';
    keyArray.forEach(key => {
        rawString += `${key}=${obj[key]}&`;
    });

    // remove last &
    rawString = rawString.substring(0, rawString.length - 1);

    if (addtionalStr) {
        rawString += addtionalStr;
    }



    return rawString;
}

let Base64Handler = {
    encryption: (str) => {
        return Buffer(str).toString('base64');
    },
    decrypt: (str) => {
        return Buffer(str, 'base64').toString();
    },
    timespan: () => {
        var date = new Date();
        return date.getFullYear().toString() + pad2(date.getMonth() + 1) + pad2(date.getDate()) + pad2(date.getHours()) + pad2(date.getMinutes()) + pad2(date.getSeconds());
    },
    genNowSeq: () => {
        return moment().format('YYYYMMDDHHmmssSSS');
    },
    getTimeStamp: () => {
        var date = new Date();
        return date.getFullYear().toString() + pad2(date.getMonth() + 1) + pad2(date.getDate()) + pad2(date.getHours()) + pad2(date.getMinutes()) + pad2(date.getSeconds());
    },
    genNonceStr: (number = 16) => {
        return crypto.randomBytes(number).toString('hex');
    },
    getClientIp: (req) => {
        let ip = req.ip;
        if (ip.substr(0, 7) === "::ffff:") {
            ip = ip.substr(7)
        }

        return ip;
    },
    /**
     * 生成n位随机数
     */
    creatRandomByNumber: (n) => {
        var rnd = "";
        for (var i = 0; i < n; i++) {
            rnd += Math.floor(Math.random() * 10);
        }
        return rnd;
    },
    encryptMd5: (obj, etcStr) => {
        return md5(encrypt(obj, etcStr)).toUpperCase();
    },
    encryptSha1: (obj, etcStr) => {
        return sha1(encrypt(obj, etcStr));
    }
}


module.exports = Base64Handler;