import NP from "number-precision";
import API from "@/api";
import { showError, Cookie } from "@/util/util.js";
import { getNetwork } from "@/util/contract.js";
import Eos from "eosjs";

export const actions = {
    setScatter: ({ commit }, scatter) => commit("setScatter", scatter),
    setEos: ({ commit }, eosjs) => commit("setEos", eosjs),
    setAccount: ({ commit }, account) => commit("setAccount", account),
    /**
     * 调起合约转账
     * @param {Object} store
     * @param {Object} params
     */
    async doDeposit({ commit, state }, params) {
        var memo;
        if (Cookie.getCookie("account") && Cookie.getCookie("token")) {
            memo = "deposit";
        } else {
            let randomCode = await API.user.getRandom({
                account: state.account.name
            });
            memo = "deposit|" + randomCode.data.data;
        }
        let player = state.account.name;
        let toAccount = state.toAccount;
        let chargeAmount = params.amount.toFixed(4) + " EOS";
        let identity = {
            authorization: [`${player}@${state.account.authority}`]
        };

        // 发出合约调用请求
        window.EOS.transfer(player, toAccount, chargeAmount, memo, identity)
            .then(trx => {
                let param = {
                    transaction_id: trx.transaction_id,
                    block_num: trx.processed.block_num
                        ? trx.processed.block_num
                        : "",
                    player: player,
                    amount: NP.times(params.amount, 10000),
                    appid: state.appid // 暂时写死
                };

                API.eos
                    .deposit(param)
                    .then(({ data }) => {
                        if (data.code === 0) {
                            let amount = NP.times(params.amount, 10000);
                            commit("updateBalance", -amount);
                            commit("updateMoney", amount);

                            params.callback && params.callback();
                        } else {
                            showError(data.msg);
                        }
                    })
                    .catch(err => {
                        showError(err);
                        params.cancel && params.cancel();
                    });
            })
            .catch(msg => {
                params.cancel && params.cancel();
                if (msg.type === "signature_rejected") {
                    return;
                }
                let json = JSON.parse(msg);
                let details = json.error.details;
                showError(details[0].message);
            });
    },

    /**
     * 调起授权登录
     * @param {Object} store
     * @param {Object} params
     */
    async doScatterLogin({ dispatch, commit, state }, params) {
        if (!state.scatter) {
            showError("Please install the scatter", "Scatter");
        } else {
            // 获取最快主网
            let networkConfig = await getNetwork().catch(error => {
                showError(error.message);
                return Promise.reject(error);
            });

            commit("setMainnet", EOS_HOST);

            // 调用getIdentity方法获取用户名
            let identity = await state.scatter
                .getIdentity({
                    accounts: [networkConfig]
                })
                .catch(error => {
                    showError(error.message);
                    return Promise.reject(error);
                });

            let accounts = identity.accounts.find(x => x.blockchain === "eos");

            commit("setAccount", accounts);

            // 如果当前登录的用户名和cookie中保存的account不一致
            // 则删除cookie中保存的account
            // 避免某些用户在移动端钱包中切换账号时跳过注销流程导致账号不一致的问题
            if (Cookie.getCookie("account") !== accounts.name) {
                Cookie.delCookie("account");
            }

            // 设置全局EOS对象
            window.EOS = state.scatter.eos(networkConfig, Eos, {});

            // 调用scatter登录成功后获取用户EOS、GT
            dispatch("getUserEOS");
            dispatch("getUserGT");
            dispatch("getAccount");

            // 每分钟刷新一次
            this.limitTimer = setInterval(() => {
                dispatch("getAccount");
            }, 60000);
        }
    },

    /**
     * 注销当前scatter账号
     * @param {Object} store
     * @param {Object} params
     */
    doScatterLoginOut({ commit, state }, params) {
        Cookie.delCookie("account");
        Cookie.delCookie("token");

        state.scatter.logout();

        clearInterval(this.limitTimer);

        commit("setAccount", "NO_LOGINING");
        commit("setBalance", 0);
        commit("setMoney", 0);
        commit("setGt", 0);
    },

    /**
     * 更新用户EOS币数量
     * @param {Object} store
     * @param {Object} params
     */
    getUserEOS({ dispatch, commit, state }, params) {
        return new Promise((resolve, reject) => {
            window.EOS.getCurrencyBalance(
                "eosio.token",
                state.account.name,
                "EOS"
            )
                .then(([balance]) => {
                    let balanceNum = Number(
                        balance.replace(/\sEOS/, "")
                    ).toFixed(4);

                    balanceNum = NP.times(balanceNum, 10000);

                    commit("setBalance", balanceNum);
                    commit("setEOSError", 0);

                    resolve();
                })
                .catch(error => {
                    // 失败重新尝试，最大尝试5次
                    commit("setEOSError", state.eosErrorCount + 1);

                    if (state.eosErrorCount <= 5) {
                        setTimeout(() => {
                            dispatch("getUserEOS");
                        }, 1000 * state.eosErrorCount);
                    }

                    reject(error);
                });
        });
    },

    /**
     * 更新用户GT币数量
     * @param {Object} store
     * @param {Object} params
     */
    getUserGT({ dispatch, commit, state }, params) {
        return new Promise((resolve, reject) => {
            window.EOS.getCurrencyBalance(
                "eosgetgtoken",
                state.account.name,
                "GT"
            )
                .then(([balance]) => {
                    let balanceNum = 0;
                    if (balance) {
                        balanceNum = Number(balance.replace(/\sGT/, ""));
                    }

                    commit("setGt", balanceNum);
                    commit("setGTError", 0);

                    resolve();
                })
                .catch(error => {
                    // 失败重新尝试，最大尝试5次
                    commit("setGTError", state.gtErrorCount + 1);

                    if (state.gtErrorCount <= 5) {
                        setTimeout(() => {
                            dispatch("getUserGT");
                        }, 1000 * state.gtErrorCount);
                    }

                    reject(error);
                });
        });
    },

    /**
     * 获取用户信息
     * @param {Object} store
     * @param {Object} params
     */
    getAccount({ commit, state }, params) {
        return new Promise((resolve, reject) => {
            window.EOS.getAccount(state.account.name)
                .then(data => {
                    // 设置CPU、NET使用率显示
                    if (data.cpu_limit && data.net_limit) {
                        commit("setLimit", {
                            cpu: data.cpu_limit.used / data.cpu_limit.max,
                            net: data.net_limit.used / data.net_limit.max
                        });
                    }

                    // 设置公钥
                    const perms = JSON.parse(JSON.stringify(data.permissions));
                    perms.forEach(v => {
                        if (v.perm_name === "active") {
                            let publicKey = v.required_auth.keys[0].key;
                            commit("setPublicKey", publicKey);
                        }
                    });
                    resolve(data);
                })
                .catch(error => {
                    reject(error);
                });
        });
    },

    /**
     * 进行验证身份登录，生成业务登录态token
     * @param {Object} store
     * @param {Object} params
     */
    async doGameLogin({ dispatch, commit, state }, params) {
        if (!state.account || state.account === "NO_LOGINING") {
            await dispatch("doScatterLogin");
        } else if (Cookie.getCookie("account") && Cookie.getCookie("token")) {
            return Promise.resolve();
        } else {
            let rData = await API.user.getRandom({
                account: state.account.name
            });
            let random = rData.data.data;
            let pubkey = state.publicKey;

            return new Promise((resolve, reject) => {
                state.scatter
                    .getArbitrarySignature(pubkey, random, "Need Login")
                    .then(sign => {
                        let param = {
                            account: state.account.name,
                            sign,
                            pubkey,
                            data: random
                        };

                        API.user.login(param).then(({ data }) => {
                            if (data.result === 1) {
                                let account = data.data.account;
                                let token = data.data.token;
                                Cookie.setCookie("account", account);
                                Cookie.setCookie("token", token);
                                resolve(data);
                            } else {
                                reject(new Error(data.msg));
                            }
                        });
                    })
                    .catch(error => {
                        reject(error);
                    });
            });
        }
    },
    /**
     * 开始一局新游戏
     */
    getNewGame({ state }){
        state.update += 1
    }
};
