import Vue from 'vue'

import 'normalize.css/normalize.css' // A modern alternative to CSS resets
import ElementUI, {Message, MessageBox} from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n
import 'font-awesome/scss/font-awesome.scss'
import '@/styles/index.scss' // global css
import moment from 'moment'

import App from './App'
import store from './store'
import router, {resetRouter} from './router'

import echarts from 'echarts'
import '@/icons' // icon
import '@/permission' // permission control
import axios from 'axios'
import 'xe-utils'
import VXETable from 'vxe-table'
import 'vxe-table/lib/index.css'

import {removeToken} from './utils/auth'
import {getBrowserToken} from './utils/commonFuc'
import {sm2 as sm222, sm2} from "sm-crypto"; // get token from cookie
Vue.prototype.$moment = moment
Vue.prototype.$echarts = echarts
Vue.use(VXETable)
/**
 * If you don't want to use mock-server
 * you want to use MockJs for mock api
 * you can execute: mockXHR()
 *
 * Currently MockJs will be used in the production environment,
 * please remove it before going online ! ! !
 */
/* if (process.env.NODE_ENV === 'production') {
  const { mockXHR } = require('../mock')
  mockXHR()
}*/

// set ElementUI lang to EN
Vue.use(ElementUI, {locale})
// 如果想要中文版 element-ui，按如下方式声明
// Vue.use(ElementUI)
Vue.prototype.$fpath = require('path')
Vue.config.productionTip = false
Vue.prototype.$axios = axios.create({
    baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
    // withCredentials: true, // send cookies when cross-domain requests
    timeout: 1000 * 60 * 10 // request timeout
})
VXETable.setup({
  validArgs: 'obsolete' // 将自定义校验参数还原为 Function(rule, cellValue, callback)
})

// 公钥Q
let publicKey2 = '041967638ca43d4577d8dba166bff4437fde944270101f398a95b846ec2f8177d09f8abc5d62b6cd2c7216274d7abe0c8e04b0bb691207a32dd2e12d6bd2798672'
// 私钥D
let privateKey1 = '27ce6eec39dbf3b564a77c4da1e129fe1ba01a92f6d61055a33ed14ffcbc949e'

Vue.prototype.$axios.interceptors.request.use(
    config => {
      // get请求映射params参数
      if (config.method === 'get' && config.params) {
        // 参数加密
        let encryptParam = doEncrypt(JSON.stringify(config.params))
        // 参数签名
        let paramSign = doSign(JSON.stringify(config.params))
        let result = 'secretData='+encryptParam+'&paramSign='+paramSign
        config.params = result
      }

      if (config.method === 'post' || config.method === 'put') {
        if (config.url!='/getMailCode'){
          if (config.data!==undefined){
            // 参数加密
            let encryptParam = doEncrypt(config.data.toString())
            // 参数签名
            let paramSign = doSign(config.data.toString())
            let result = 'secretData='+encryptParam+'&paramSign='+paramSign
            config.data = result
          }
        }
      }

      if (getBrowserToken()) { // 判断是否存在token，如果存在的话，则每个http header都加上token
        let tokenStr = doEncrypt(getBrowserToken())
        config.headers['Authorization']= tokenStr
        config.headers['TokenSign']= doSign(getBrowserToken())
      }
      return config
    },
    error => {
        // do something with request error
        console.log(error) // for debug
        return Promise.reject(error)
    }
)

function getBrowserUser() {
    var user = "";
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i].trim();
        if (c.indexOf("user=") == 0){
            user = c.substring("user=".length, c.length);
        }
    }
    return user
}

// response interceptor
Vue.prototype.$axios.interceptors.response.use(
    /**
     * If you want to get http information such as headers or status
     * Please return  response => response
     */

    /**
     * Determine the request status by custom code
     * Here is just an example
     * You can also judge the status by HTTP Status Code
     */
    response => {
        // 处理下载文件
        if (response.headers && response.headers['content-type'] && (response.headers['content-type'].indexOf('application/x-msdownload') != -1)) {
            // 创建一个blob对象,file的一种
            const blob = new Blob([response.data], {type: response.headers['content-type']})
            const fileName = decodeURI(response.headers['content-disposition'].split('=')[1])
            if (window.navigator.msSaveOrOpenBlob) {
                // 兼容IE10
                navigator.msSaveBlob(blob, fileName)
            } else {
                // 非IE下载
                const elink = document.createElement('a')
                elink.download = fileName
                elink.style.display = 'none'
                elink.href = URL.createObjectURL(blob)
                document.body.appendChild(elink)
                elink.click()
                URL.revokeObjectURL(elink.href) // 释放URL 对象
                document.body.removeChild(elink)
            }
            response.data = ''
            response.headers['content-type'] = 'text/json'
            return response
        } else {
            const res = response.data
            let returnStr = res.split("&")
            let returnData = returnStr[0].split("=")[1]
            let returnSign = returnStr[1].split("=")[1]
            // 解密
            let decData = doDecryptStr(returnData)
            // 验签
            let verifyResult = doVerifySignature(decData,returnSign)

          if (!verifyResult){
            return Promise.reject(new Error('返回数据验签失败' || 'Error'))
          }

          let data = JSON.parse(decData)
          alert(data)
            // if the custom code is not 20000, it is judged as an error.
            //console.log(res.code)
            if (data.code !== 0) {
                Message({
                    message: data.message || 'Error',
                    type: 'error',
                    duration: 5 * 1000
                })

                // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
                if (data.code === 50008 || data.code === 50012 || data.code === 50014) {
                    // to re-login
                    MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
                        confirmButtonText: 'Re-Login',
                        cancelButtonText: 'Cancel',
                        type: 'warning'
                    }).then(() => {
                        store.dispatch('user/resetToken').then(() => {
                            location.reload()
                        })
                    })
                }
                return Promise.reject(new Error(data.message || 'Error'))
            } else {
                return data
            }
        }
    },
    error => {
        if (error.response) {
            switch (error.response.status) {
                case 401:
                    console.log('用户验证失败！')
                    // 返回 401 清除token信息并跳转到登录页面
                    removeToken()
                    resetRouter()
                    Message({
                        message: error.response.data,
                        type: 'error',
                        duration: 5 * 1000
                    })
                    break
                case 403:
                    console.log('登录超时！')
                    // 返回 401 清除token信息并跳转到登录页面
                    removeToken()
                    resetRouter()
                    router.push('/login')
                    Message({
                        message: '登录超时',
                        type: 'error',
                        duration: 5 * 1000
                    })
                    break
                case 500:
                    Message({
                        message: '服务器关闭了！请联系相关工作人员',
                        type: 'error',
                        duration: 5 * 1000
                    })
                    removeToken()
                    resetRouter()
                    router.push('/login')
                    break
                case 504:
                    console.log('服务器关闭了！')
                    resetRouter()
                    break
            }
        }
        /*    console.log('err' + error) // for debug
        Message({
          message: error.message,
          type: 'error',
          duration: 5 * 1000
        })*/
        return Promise.reject(error)
    }
)

new Vue({
    el: '#app',
    router,
    store,
    render: h => h(App)
})

export function test(){
  let sm2 = require('sm-crypto').sm2;
  let cipherMode = 1
  // 加密
  let encryptData = sm2.doEncrypt('1122加密', '0460ff8c8c306fe62f6f9d11c5c82c30d10bbbc703da094e423072cac7dc663c97fad52eccb34f311f47a07f280de157ba4f2aa659cabe749121384b9376ea2ed2', cipherMode);
  let sm3 = require('sm-crypto').sm2;
  // 签名
  let sign = sm3.doSignature('1122加密','6155d63ee27cbeca07f3e40c4f8856f1be8119fcbda1aadc7e0e595e52bad7bd')
  // 解密
  let sm4 = require('sm-crypto').sm2;
  let doDecrypt = sm4.doDecrypt(encryptData, privateKey1, cipherMode);
  alert('解密：'+doDecrypt)
  // 验签
  let sm5 = require('sm-crypto').sm2;
  let verifyResult = sm5.doVerifySignature(doDecrypt, sign, publicKey2) // 验签结果
  alert('验签：'+verifyResult)
}

// 加密：
export function doEncrypt(msgString) {
  // let msg = msgString;
  // if (typeof (msgString) !== 'string') {
  //   msg = JSON.stringify(msgString);
  // }
  let sm2 = require('sm-crypto').sm2;
  // 1 - C1C3C2；	0 - C1C2C3；	默认为1
  let cipherMode = 1

  // 加密结果
  let encryptData = sm2.doEncrypt(msgString, publicKey2, cipherMode);
  // 加密后的密文前需要添加04，后端才能正常解密
  // let encrypt = '04' + encryptData;
  return encryptData;
}

// 解密
export function doDecryptStr(enStr) {
  // let msg = enStr;
  // if (typeof (enStr) !== 'string') {
  //   msg = JSON.stringify(enStr);
  // }

  let sm2 = require('sm-crypto').sm2;
  // 1 - C1C3C2；	0 - C1C2C3；	默认为1
  let cipherMode = 1

  // 加密后的密文，需要前去掉04。因为doDecrypt中自行添加了04，后端加密代码也自行添加了04
  // let en = enStr.data.substr(2)
  // 解密结果
  let doDecrypt = sm2.doDecrypt(enStr, privateKey1, cipherMode);
  // 解密后类型转换
  let objData = JSON.parse(doDecrypt)
  return doDecrypt;
}

// 签名
export function doSign(msgString) {
  let sm2 = require('sm-crypto').sm2;
  // 1 - C1C3C2；	0 - C1C2C3；	默认为1
  let cipherMode = 1
  // 签名
  let sign = sm2.doSignature(msgString,privateKey1, { hash:true, der:true })
  return sign;
}

// 验签
export function doVerifySignature(msgString,sigValueHex) {
  let sm2 = require('sm-crypto').sm2;
  // 1 - C1C3C2；	0 - C1C2C3；	默认为1
  let cipherMode = 1
  // 签名
  let verifyResult = sm2.doVerifySignature(msgString, sigValueHex, publicKey2,{ hash:true, der:true }) // 验签结果
  return verifyResult;
}
