import {socket} from "@/socket.js";
import {useStore} from "@/store/store.js";
import {flushWalletTransactions} from "@/blockchain/wallet.js";
import {parseElaboratedOrderStatus} from "@/blockchain/orderlib.js";
import {DataFeed} from "./charts/datafeed";
import {notifyFillEvent} from "@/notify.js";
import {refreshOHLCSubs} from "@/blockchain/ohlcs.js";

socket.on('connect', () => {
    console.log('ws connected')
    const s = useStore();
    s.connected = true
    if (s.chainId && s.account)
        socket.emit('address', s.chainId, s.account)
    refreshOHLCSubs()
})

socket.on('disconnect', () => {
    console.log('ws disconnected')
    useStore().connected = false
})

socket.on('connect_error', (err) => {
    console.log('ws connect error', err)
    useStore().connected = false
})

socket.on('error', (err) => {
    console.log('ws error', err)
    useStore().connected = false
})

socket.on('approvedRegion', (approved) => {
    console.log('approved region', approved)
    useStore().regionApproved = approved
})

socket.on('approvedWallet', (approved) => {
    console.log('approved wallet', approved)
    useStore().walletApproved = approved
})

socket.on('p', async (chainId, pool, price) => {
    console.log('pool price from message', chainId, pool, price)
    const s = useStore()
    if( s.chainId !== chainId )
        return
    s.poolPrices[[chainId,pool]] = price
})

socket.on('ohlc', async (chainId, poolPeriod, ohlcs) => {
    // console.log('pool bars', poolPeriod, ohlcs)
    if (ohlcs && ohlcs.length) {
        const split = poolPeriod.indexOf('|')
        const pool = poolPeriod.slice(0,split)
        useStore().poolPrices[[chainId, pool]] = parseFloat(ohlcs[ohlcs.length - 1][4]) // closing price
    }
    DataFeed.poolCallback(chainId, poolPeriod, ohlcs)
})

socket.on('vb', async (chainId, vault, balances) => {
    const s = useStore()
    if( s.chainId !== chainId )
        return
    console.log('vb', vault, balances)
    s.vaultBalances[vault] = JSON.parse(balances)
    console.log('vault balances', vault, s.vaultBalances[vault])
})

socket.on('vaults', (chainId, owner, vaults)=>{
    const s = useStore()
    console.log('vaults', chainId, owner, vaults)
    if( s.chainId !== chainId || s.account !== owner )
        return
    if( vaults.length > s.vaults.length ) {
        s.vaults = vaults
        if( vaults.length ) {
            const vault = vaults[0]
            flushWalletTransactions(chainId, owner, 0, vault)
        }
    }
})

socket.on('mark.usd', (chainId, token, value)=>{
    const s = useStore()
    s.markPrices[`${chainId}|${token}`] = Number(value)
    // console.log('mark.usd', token, value)
})

function handleOrderStatus(chainId, vault, orderIndex, status) {
    const s = useStore()
    if( s.chainId !== chainId )
        return
    // message 'o' is a single order status
    const parsed = parseElaboratedOrderStatus(chainId, status);
    // console.log('o', chainId, vault, orderIndex, status, parsed)
    if( !(vault in s.orders) )
        s.orders[vault] = {}
    s.orders[vault][orderIndex] = parsed
}

socket.on('os', (chainId, vault,  orders) => {
    // message 'os' has multiple order statuses
    console.log('os', orders)
    for( const [orderIndex, status] of orders )
        handleOrderStatus(chainId, vault, orderIndex, status)
})

socket.on( 'o', handleOrderStatus)

socket.on( 'of', (chainId, vault, orderIndex, filled)=>{
    const s = useStore()
    if( s.chainId !== chainId )
        return
    console.log('of', chainId, vault, orderIndex, filled)
    if( !(vault in s.orders) ) {
        console.log('warning: got fill on an order in an unknown vault')
        return
    }
    if( !(orderIndex in s.orders[vault]) ) {
        console.log(`warning: orderIndex ${orderIndex} missing from vault ${vault}`)
        return
    }

    const status = s.orders[vault][orderIndex]
    console.log('apply fills', status, filled)

    let orderIn = 0n
    let orderOut = 0n
    for (const i in filled) {
        const ts = status.trancheStatus[i]
        let filledIn = 0n
        let filledOut = 0n
        const [activationTime, fills] = filled[i];
        const numOld = ts.fills.length;
        for (let i=0; i<fills.length; i++) {
            const fill = fills[i]
            let [tx, time, fi, fo, fee] = fill
            fi = BigInt(fi)
            fo = BigInt(fo)
            fee = BigInt(fee)
            filledIn += fi
            filledOut += fo
            if (i>=numOld) {
                // new fill detected
                const f = {tx, time, filledIn: fi, filledOut: fo, fee, filled: status.order.amountIsInput ? fi : fo};
                console.log('new fill', f)
                notifyFillEvent(chainId, status, i, f).catch((e)=>console.log('fill notification error', e))
                ts.fills.push(f)
            }
        }
        ts.filledIn = filledIn
        ts.filledOut = filledOut
        ts.activationTime = activationTime
        orderIn += filledIn
        orderOut += filledOut
    }
    status.filledIn = orderIn
    status.filledOut = orderOut
    status.filled = status.order.amountIsInput ? orderIn : orderOut

    console.log('apply fills completed', status)
})

console.log('initialized socketio')