/*
 * @Author: Rindy
 * @Date: 2019-08-06 16:25:08
 * @LastEditors: Rindy
 * @LastEditTime: 2020-07-29 17:36:36
 * @Description: Request
 */

import logger from './logger'
import browser from './browser'
import { base64ToBlob } from './file'
import { checkLogin } from "@/api";
import { LoginDetector } from "@/utils/starter";
import { $alert, $loginTips } from '@/components/shared/message'
import { $waiting } from '@/components/shared/loading'


// 空函数
const noop = function() {}
// 请求回调队列
let postQueue = []

export const statusCode = {
    NEXT: -999, //继续执行 
    SUCCESS: 0, //成功
    EXCEPTION: -1, //异常错误
    EXCEPTION_FUWU: 1, //服务异常

    FAILURE_CODE_3001: 3001, //模型重复
    FAILURE_CODE_3002: 3002, //户型重复

    FAILURE_CODE_7007: 7007, //房源不存在
    FAILURE_CODE_7008: 7008, //有关联场景使用此场景，不能删除
    FAILURE_CODE_7005: 7005, //审核中不能编辑
    FAILURE_CODE_7006: 7006, //已审核不能编辑
    FAILURE_CODE_5001: 5001, //token失效
    FAILURE_CODE_60001: 60001 //场景名称不能为空

    
    
}

/**
 * 已知错误提示集合
 */
// const defineErrorCode = []

let __showNetworkError = false
let __showNoHouseError = false



const showLoginTips = () => {
    // 防止多次请求弹出
    if (showLoginTips.__is_show) {
        return
    }

    showLoginTips.__is_show = true

    return $loginTips({
        title: '提示',
        okText: '去登录',
        noText: '登录完毕，继续',
        content: '您没有登录，请登录后再编辑',
        okLink: '/evergrande/#/login',
        ok: function() {
            showLoginTips.__is_show = false
            return false
        },
        no: function() {
            checkLogin().then(response => {
                if (response.code === statusCode.SUCCESS) {
                    postQueue.length && postQueue.forEach(item => item())
                    postQueue = []
                    LoginDetector.valid();
                } else if (response.code === statusCode.FAILURE_CODE_5001) {
                    showLoginTips()
                }
            })
            showLoginTips.__is_show = false
        }
    })
}


export function getToken() {
    return browser.urlHasValue('token', true) || localStorage.getItem('token') || ''
}

export function statusCodesHandler(result, callback) {
    if (result.code == statusCode.FAILURE_CODE_7005) {
        return $alert({ 
            content: '该VR项目待审核，不可编辑。',
            forceOK:true,
              ok:()=>{
                window.location.reload()
        }})
    }

    if (result.code == statusCode.FAILURE_CODE_60001) {
        return $alert({ 
            content: '场景名称不能为空'})
    }


    if (result.code == statusCode.FAILURE_CODE_3001) {
        return $alert({ 
            content: 'VR模型已存在，不能重复添加'})
    }


    if (result.code == statusCode.FAILURE_CODE_3002) {
        return $alert({ 
            content: '户型已存在，不能重复添加'})
    }

    

    if (result.code == statusCode.FAILURE_CODE_7006) {
        return $alert({ 
            content: '该VR项目已审核，不可编辑。',
            forceOK:true,
              ok:()=>{
                window.location.reload()
        }})
    }

    if (result.code == statusCode.FAILURE_CODE_7008) {
        if (__showNoHouseError) {
            return
        }
        __showNoHouseError = true
        return $alert({ 
            content: `此场景有被热点关联，不能删除`,
            forceOK:true,
              ok:()=>{
                __showNoHouseError = false
                $waiting.hide()
            }})
    }

    if (result.code == statusCode.FAILURE_CODE_7007) {
        if (__showNoHouseError) {
            return
        }
        __showNoHouseError = true
        return $alert({ 
            content: `房源不存在`,
            forceOK:true,
              ok:()=>{
                __showNoHouseError = false
                $waiting.hide()
            }})
    }

    if (result.code == statusCode.EXCEPTION||result.code == statusCode.EXCEPTION_FUWU) {
        if (__showNoHouseError) {
            return
        }
        __showNoHouseError = true
        return $alert({
            content: `${result.msg}`,
            forceOK:true,
            ok:()=>{
            __showNoHouseError = false
            $waiting.hide()
        }})
    }

    

    if (result.code == statusCode.FAILURE_CODE_5001) {
        callback(result.code)
        return showLoginTips()
    }

    return statusCode.NEXT
}

$.ajaxSetup({
    headers: {},
    beforeSend: function(xhr) {
        const token = getToken()
        if (token) {
            xhr.setRequestHeader("token", token)
        }
    },
    error: function() { // 出错时默认的处理函数
        if (__showNetworkError) {
            return
        }
        __showNetworkError = true
        $alert({content: '网络异常，请稍后再试',
                forceOK:true,
                ok:()=>{
                    __showNetworkError = false
            }})
        return 
    },
    success: function() {

    },
    complete: function(data) {
        // Post类型请求无论成功或失败都关闭等待提示
        if (this.type === 'POST'&& this.url.indexOf('pano/scene/uploadPano') == -1) {
            let isLongpolling = ''
            try {
                 isLongpolling = JSON.parse(this.data).islongpolling
            } catch (error) {
                error
            }
            (http.__loading && !isLongpolling) && $waiting.hide()
        }

        http.__loading = true
    }
});

export const http = {
    statusCode,
    __loading: true,
    __request(xhr, method, url, data, done, fail) {
        if (typeof done != 'function') {
            done = noop
        }
        if (typeof fail != 'function') {
            fail = noop
        }

        xhr.done(result => {
            if (typeof result.code !== 'undefined') {
                const flag = statusCodesHandler(result, function(code) {
                    // 需要登录的状态
                    if (code == statusCode.FAILURE_CODE_5001) {
                        postQueue.push(function() {
                            http[method](url, data, done, fail)
                        })
                        // if (url.indexOf('isLogin') == -1) {
                        //     postQueue.push(function() {
                        //         http[method](url, data, done, fail)
                        //     })
                        // }
                    }
                })

                if (flag === statusCode.NEXT) {
                    done(result, result.code == 0)
                }

            } else {
                done(result)
            }
        })

        xhr.fail(fail)

        xhr.always(() => xhr = null)

        return xhr
    },
    /**
     * Get请求
     * @param {String} url 请求地址
     * @param {Object?} data 请求参数
     * @param {Function?} done 成功回调
     * @param {Function?} fail 失败回调
     */
    get(url, data = {}, done, fail) {
        if (/\.json/.test(url)) {
            // json文件格式自动调用getJson方法
            return this.getJson(url, data, done, fail)
        }
        return this.__request($.get(url, data), 'get', url, data, done, fail)
    },
    /**
     * Get Blob请求
     * @param {String} url 请求地址
     * @param {Object?} data 请求参数
     * @param {Function?} done 成功回调
     * @param {Function?} fail 失败回调
     */
    getText(url, data = {}, done, fail) {
        return this.__request($.ajax({
            url: url,
            dataType: "text",
        }), 'getText', url, data, done, fail)
    },
    /**
     * GetJson请求 读取json文件数据
     * @param {String} url 请求地址
     * @param {Object?} data 请求参数
     * @param {Function?} done 成功回调
     * @param {Function?} fail 失败回调
     */
    getJson(url, data = {}, done, fail) {
        return this.__request($.getJSON(url, data), 'get', url, data, done, fail)
    },
    /**
     * Get Blob请求
     * @param {String} url 请求地址
     * @param {Object?} data 请求参数
     * @param {Function?} done 成功回调
     * @param {Function?} fail 失败回调
     */
    getBlob(url, data = {}, done, fail) {
        return this.__request($.ajax({
            url: url,
            dataType: "blob",
        }), 'getBlob', url, data, done, fail)
    },
    /**
     * Get Arraybuffer请求
     * @param {String} url 请求地址
     * @param {Object?} data 请求参数
     * @param {Function?} done 成功回调
     * @param {Function?} fail 失败回调
     */
    getArraybuffer(url, data = {}, done, fail) {
        return this.__request($.ajax({
            url: url,
            dataType: "arraybuffer",
        }), 'getArraybuffer', url, data, done, fail)
    },
    /**
     * Post 请求
     * @param {String} url 请求地址
     * @param {Object?} data 请求参数
     * @param {Function?} done 成功回调
     * @param {Function?} fail 失败回调
     */
    post(url, data = {}, done, fail) {
        if (url.indexOf('isLogin') == -1) {
            http.__loading && $waiting.show()
        }

        return this.__request($.post(url, data), 'post', url, data, done, fail)
    },
    /**
     * PostJson 请求
     * @param {String} url 请求地址
     * @param {Object?} data 请求参数
     * @param {Function?} done 成功回调
     * @param {Function?} fail 失败回调
     */
    postJson(url, data = {}, done, fail) {
        (http.__loading && !data.islongpolling) && $waiting.show()
        return this.__request($.ajax({
            type: "POST",
            url: url,
            contentType: 'application/json',
            data: JSON.stringify(data)
        }), 'postJson', url, data, done, fail)
    },
    /**
     * Post 表单 支持文件上传
     * @param {String} url 请求地址
     * @param {FormData?} formData 请求参数
     * @param {Function?} done 成功回调
     * @param {Function?} fail 失败回调
     */
    postForm(url, formData, done, fail, onProgress) {
        if (typeof onProgress === "function") {
            return this.__request($.ajax({
                type: "POST",
                url: url,
                processData: false,
                contentType: false,
                data: formData,
                xhr: function() {
                    const xhr = new XMLHttpRequest();
                    xhr.upload.addEventListener('progress', function(e) {
                        onProgress((e.loaded / e.total) * 100 + '%')
                    })
                    return xhr;
                },
            }), 'postForm', url, formData, done, fail)
        } else {
            http.__loading && $waiting.show()
            return this.__request($.ajax({
                type: "POST",
                url: url,
                processData: false,
                contentType: false,
                data: formData
            }), 'postForm', url, formData, done, fail)
        }
    },
    /**
     * 加载图片
     * @param {String} url 请求地址
     * @param {Number?} retry 重试次数,默认为3
     */
    loadImage(url, retry = 3) {
        const def = $.Deferred();
        const img = new Image;

        const load = () => {
            logger.warn("Retrying load image: " + url);
            this.loadImage(url, retry - 1).done(def.resolve.bind(def)).progress(def.notify.bind(def)).fail(def.reject.bind(def));
        }

        img.onerror = function() {
            retry > 0 ? setTimeout(() => load(), 1e3) : def.reject(`[${url}]加载失败`)
        }

        img.onload = function() {
            def.resolve(img)
        }

        img.crossOrigin = "anonymous";
        img.src = url;

        return def;
    },
    /**
     * 上传文件
     * @param {String} url 请求地址
     * @param {Object?} data 请求参数
     * @param {Function?} done 成功回调
     * @param {Function?} fail 失败回调
     */
    uploadFile(url, data = {}, done, fail, onProgress) {
        const form = new FormData()
        // if (file.needTransfer) { //ie和苹果都不支持dataURLtoFile得传送,所以只能用blob
        //     form.append("file", common.dataURLtoBlob(file.file), file.name || file.file.name);
        // } else {
        //     form.append("file", file.file, file.name || file.file.name);
        // }
        for (let key in data) {
            if (key == 'file') {
                form.append("file", data[key], data.filename || data[key].name);
            } else if (key != 'filename') {
                form.append(key, data[key])
            }
        }
        return this.postForm(url, form, done, fail, onProgress)
    },
    /**
     * 上传文件
     * @param {String} url 请求地址
     * @param {Object?} data 请求参数 {file:'base64 string',filename:'image.jpg',...}
     * @param {Function?} done 成功回调
     * @param {Function?} fail 失败回调
     */
    uploadBlobFile(url, data = {}, done, fail) {
        const form = new FormData()
        for (let key in data) {
            if (key === 'file') {
                form.append("file", base64ToBlob(data.file), data.filename);
            } else if (key != 'filename') {
                form.append(key, data[key])
            }
        }
        return this.postForm(url, form, done, fail)
    }
}