/**
 * 微信登录客户端支持
 */
import {base64} from '../util/string.ts';

type WxLoginOptions = {
    id: string;
    appid: string;
    scope: string;
    redirect_uri: string;
    state: any;
    styletype?: string;
    sizetype?: string;
    bgcolor?: string;
    rst?: string;
    style?: string;
    href?: string;
    lang?: 'en' | string;
    stylelite?: number;
    fast_login?: number;
    color_scheme?: 'auto' | 'dark' | 'light';
    onReady?: (ready: boolean) => void;
    onQRcodeReady?: () => void;
    onCleanup?: () => void;
    self_redirect?: boolean;
};

(function (e: Window, t: Document) {
    (e as any).WxLogin = function (o: WxLoginOptions) {
        let n = "default";
        if (o.self_redirect === true) {
            n = "true";
        } else if (o.self_redirect === false) {
            n = "false";
        }
        const r = t.createElement("iframe") as HTMLIFrameElement;
        const s = (new Date).getTime();
        let a = "https://open.weixin.qq.com/connect/qrconnect?appid=" + o.appid + "&scope=" + o.scope + "&redirect_uri=" + o.redirect_uri + "&state=" + o.state + "&login_type=jssdk&self_redirect=" + n + "&styletype=" + (o.styletype || "") + "&sizetype=" + (o.sizetype || "") + "&bgcolor=" + (o.bgcolor || "") + "&rst=" + (o.rst || "") + "&ts=" + s;
        a += o.style ? "&style=" + o.style : "";
        a += o.href ? "&href=" + o.href : "";
        a += o.lang === "en" ? "&lang=en" : "";
        a += o.stylelite === 1 ? "&stylelite=1" : "";
        a += o.fast_login === 0 ? "&fast_login=0" : "";
        if (o.color_scheme === "auto") {
            a += "&color_scheme=auto";
        } else if (o.color_scheme === "dark") {
            a += "&color_scheme=dark";
        } else if (o.color_scheme === "light") {
            a += "&color_scheme=light";
        }
        r.src = a;
        r.setAttribute("frameBorder", "0");
        r.setAttribute("allowTransparency", "true");
        r.setAttribute("scrolling", "no");
        r.style.width = "300px";
        r.style.height = "400px";
        r.allow = "local-network-access";
        const c = t.getElementById(o.id);
        if (c && e.addEventListener && (e as any).JSON) {
            c.innerHTML = "";
            c.appendChild(r);
            const i = function (evt: MessageEvent) {
                if (evt.origin === "https://open.weixin.qq.com") {
                    try {
                        const n = JSON.parse((evt as any).data);
                        if (n && n.type === "status") {
                            const ready = n.status === "wxReady";
                            if (ready && o.onReady && typeof o.onReady === "function") {
                                o.onReady(ready);
                            }
                            if (n.status === "wxQRcodeReady" && o.onQRcodeReady && typeof o.onQRcodeReady === "function") {
                                o.onQRcodeReady();
                            }
                        }
                    } catch (err) {
                        if (console && typeof console.log === "function") {
                            console.log("wxLogin postMessage error", err);
                        }
                    }
                }
            };
            e.addEventListener("message", i, false);
            let l = false;
            o.onCleanup = function () {
                if (!l && e.removeEventListener) {
                    e.removeEventListener("message", i, false);
                    l = true;
                }
            }
        }
    }
})(window, document);

// 以上代码改编自 http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js


function standardizeRedirectUri(redirectUri: string, productContextUri: string): string {
    let protocol = window.location.protocol;
    let host = window.location.host;
    let uri = protocol + '//' + productContextUri;
    if (productContextUri.startsWith(host)) {
        uri += redirectUri;
    } else { // 不是生产环境则借助于生产环境的直接重定向能力进行再跳转
        uri += '/redirect/';
        if (redirectUri.startsWith('/')) { // 目标跳转地址是相对地址，则加上当前网站根地址
            uri += protocol.substring(0, protocol.length - 1) + '/' + host + redirectUri;
        } else { // 不以/开头，视为绝对地址
            let index = redirectUri.indexOf('://');
            if (index < 0) { // 绝对地址中一定包含://
                console.error('错误的跳转目标地址：' + redirectUri);
                return;
            }
            uri += redirectUri.substring(0, index); // 协议部分
            uri += redirectUri.substring(index + 2);
        }
    }
    return encodeURI(uri);
}

function standardizeState(state) {
    let stateString = '';
    if (typeof state === 'object') {
        stateString = JSON.stringify(state);
        stateString = base64.encode(stateString);
        if (stateString.length > 128) {
            delete state._next;
            stateString = JSON.stringify(state);
            stateString = base64.encode(stateString);
        }
    }
    return stateString;
}

export default class Wechat {

    appId = '';
    productContextUri = '';

    constructor(appId, productContextUri) {
        this.appId = appId;
        this.productContextUri = productContextUri;
    }

    login(containerId, redirectUri, options) {
        options = options || {};
        if (options.cssHref && options.cssHref.startsWith('/')) {
            options.cssHref = window.location.protocol + '//' + window.location.host + options.cssHref;
        }

        new window.WxLogin({
            id: containerId,
            appid: this.appId,
            scope: "snsapi_login",
            redirect_uri: standardizeRedirectUri(redirectUri, this.productContextUri),
            href: options.cssHref,
            state: standardizeState(options.state),
        });
    }

    authorize(redirectUri, state, silent) {
        // 请求参数有严格的顺序要求，不能更改参数顺序
        let url = window.location.protocol + '//open.weixin.qq.com/connect/oauth2/authorize?appid=' + this.appId;
        url += '&redirect_uri=' + standardizeRedirectUri(redirectUri, this.productContextUri);
        url += '&response_type=code';
        url += '&scope=' + (silent ? 'snsapi_base' : 'snsapi_userinfo');
        state = standardizeState(state);
        if (state) {
            url += '&state=' + state;
        }
        window.location.href = url;
    }

}
