import time

from sqlTools import *
from web3Tools import *


def baseTokenLPUpdata():
    topLP = EthMevModel.find_by_block('topLP')['data'] + EthMevModel.find_by_block('normalLp')['data']
    printTime('TOP LP:', len(topLP))
    tradeToken0 = False
    for baseTokenI in baseTokenInfo:
        baseTokenIAddress = baseTokenI.lower()
        baseTokenLp = {}
        baseTokenINmae = baseTokenInfo[baseTokenI]['name']
        for lp0 in topLP:
            try:
                dataI = json.loads(lp0['data'])
                lp0Token0 = dataI['token0'].lower()
                lp0Token1 = dataI['token1'].lower()
                lp0Address = dataI['LP'].lower()
                # hei LP filter
                if lp0Address in heiLp or lp0Token0 in heiLp or lp0Token1 in heiLp:
                    continue

                lp0Factory = dataI['factory'].lower()
            except BaseException as err:
                printTime(traceback.format_exc())
                printTime(dataI, err)

            if lp0Factory not in topFactoryFee:
                continue
            if lp0Token0 == baseTokenIAddress:
                tradeToken0 = lp0Token1
            elif lp0Token1 == baseTokenIAddress:
                tradeToken0 = lp0Token0
            else:
                continue
            if tradeToken0 not in baseTokenLp:
                baseTokenLp[tradeToken0] = []
            baseTokenLp[tradeToken0].append(lp0Address)
        pushText(baseTokenLp, baseTokenIAddress)


def topLPUpdata():
    lpArray = {}
    topLP = EthMevModel.find_by_block('topLP')['data'] + EthMevModel.find_by_block('normalLp')['data'] + bugLp
    printTime('TOP LP:', len(topLP))
    baseTokenLp = {}
    for baseTokenI in baseTokenInfo:
        baseTokenIAddress = baseTokenI.lower()
        baseTokenLp[baseTokenIAddress] = {}

    for lp0 in topLP:
        try:
            dataI = json.loads(lp0['data'])
            lp0Token0 = dataI['token0'].lower()
            lp0Token1 = dataI['token1'].lower()
            lp0Address = dataI['LP'].lower()
            if 'factory' not in dataI:
                continue
            if dataI['router'] == '0x68b3465833fb72a70ecdf485e0e4c7bd8665fc45':
                continue
            if 'r0' in dataI and int(dataI['r0']) < 405:
                continue
            if 'r1' in dataI and int(dataI['r1']) < 405:
                continue
            # hei LP filter
            if lp0Address in heiLp or lp0Token0 in heiLp or lp0Token1 in heiLp:
                continue
            lp0Factory = dataI['factory'].lower()
            if lp0Factory not in topFactoryFee:
                continue
        except BaseException as err:
            printTime(traceback.format_exc())
            printTime(dataI, err)
        lpArray[lp0Address] = {}
        lpArray[lp0Address]['factory'] = lp0Factory
        lpArray[lp0Address]['token0'] = lp0Token0
        lpArray[lp0Address]['token1'] = lp0Token1
        lpArray[lp0Address]['LP'] = lp0Address
        lpArray[lp0Address]['fee'] = topFactoryFee[lp0Factory]

        if lp0Token0 in baseTokenLp:
            tradeToken = lp0Token1
            if tradeToken not in baseTokenLp[lp0Token0]:
                baseTokenLp[lp0Token0][tradeToken] = []
            baseTokenLp[lp0Token0][tradeToken].append(lp0Address)

        if lp0Token1 in baseTokenLp:
            tradeToken = lp0Token0
            if tradeToken not in baseTokenLp[lp0Token1]:
                baseTokenLp[lp0Token1][tradeToken] = []
            baseTokenLp[lp0Token1][tradeToken].append(lp0Address)

    for baseToken in  baseTokenLp:
        pushText(baseTokenLp[baseToken], baseToken)
    pushText(lpArray, 'topLP')


def aba(baseToken, endToken):
    # WETH
    baseToken = baseToken.lower()
    # WETH WETHW
    endToken = endToken.lower()
    # WETH. {A:[LP0, LP1, LP2] B:[...]...}
    baseTokenArray = readText(baseToken)
    endTokenArray = readText(endToken)
    baseToken_endTokenArray = []
    # tradeToken0 = WETH.A,B,C....
    # WETH - X 中按token for in
    for tradeToken0 in baseTokenArray:
        # tradeLP0 = A:[LP0, LP1, LP2] WETH - X LP中 for in 所有LP
        if tradeToken0 not in endTokenArray:
            continue

        for tradeLP0 in baseTokenArray[tradeToken0]:
            # 所有LP中for in
            for tradeLP1 in endTokenArray[tradeToken0]:
                if tradeLP1 == tradeLP0:
                    continue
                if tradeLP0 not in topLpInfo:
                    printTime(tradeLP0, 'not in topLpInfo')
                if tradeLP1 not in topLpInfo:
                    printTime(tradeLP1, 'not in topLpInfo')
                tradeInfoLp0 = {}
                tradeInfoLp0['lp'] = tradeLP0
                tradeInfoLp0['inToken'] = baseToken
                tradeInfoLp0['outToken'] = tradeToken0
                tradeInfoLp0['fee'] = topFactoryFee[topLpInfo[tradeLP0]['factory']]
                if tradeInfoLp0['inToken'] < tradeInfoLp0['outToken']:
                    tradeInfoLp0['indexIn'] = 0
                else:
                    tradeInfoLp0['indexIn'] = 1

                tradeInfoLp1 = {}
                tradeInfoLp1['lp'] = tradeLP1
                tradeInfoLp1['inToken'] = tradeToken0
                tradeInfoLp1['outToken'] = endToken
                tradeInfoLp1['fee'] = topFactoryFee[topLpInfo[tradeLP1]['factory']]
                if tradeInfoLp1['inToken'] < tradeInfoLp1['outToken']:
                    tradeInfoLp1['indexIn'] = 0
                else:
                    tradeInfoLp1['indexIn'] = 1
                baseToken_endTokenArray.append([tradeInfoLp0, tradeInfoLp1])

    pushText(baseToken_endTokenArray, 'aba' + baseToken + endToken)


def pushABA():
    for i in baseTokenInfo:
        i = i.lower()
        aba(i, i)
    aba(WETH, WETHW)
    aba(WETHW, WETH)


def readABA():
    array = []
    for i in baseTokenInfo:
        i = i.lower()
        iiArray = readText('aba' + i + i)
        array = array + iiArray
    array = array + readText('aba' + WETHW + WETH)
    array = array + readText('aba' + WETH + WETHW)
    return array


def findLpRouter(lp, lpRouter):
    lpTradeArray = []
    for lpArray in lpRouter:
        for lpI in lpArray:
            if lpI['lp'] == lp:
                lpTradeArray.append(lpArray)
                break
    return lpTradeArray


def abca(baseToken, endToken):
    baseToken = baseToken.lower()
    endToken = endToken.lower()
    baseTokenArray = readText(baseToken)
    endTokenArray = readText(endToken)
    baseToken_endTokenArray = []
    # tradeToken0 = B
    for tradeToken0 in baseTokenArray:
        for tradeLP0 in baseTokenArray[tradeToken0]:
            for tradeLP1 in topLpInfo:
                if tradeLP1 == tradeLP0:
                    continue
                # 以上和ABA一样
                tradeLP1Token0 = topLpInfo[tradeLP1]['token0']
                tradeLP1Token1 = topLpInfo[tradeLP1]['token1']

                # baseToken = A
                # tradeToken1 = C
                if tradeLP1Token0 == tradeToken0:
                    tradeToken1 = tradeLP1Token1
                elif tradeLP1Token1 == tradeToken0:
                    tradeToken1 = tradeLP1Token0
                else:
                    continue
                if tradeToken1 in endTokenArray:
                    for tradeLP2 in endTokenArray[tradeToken1]:
                        if tradeLP2 == tradeLP0:
                            continue

                        tradeInfoLp0 = {}
                        tradeInfoLp0['lp'] = tradeLP0
                        tradeInfoLp0['inToken'] = baseToken
                        tradeInfoLp0['outToken'] = tradeToken0
                        tradeInfoLp0['fee'] = topFactoryFee[topLpInfo[tradeLP0]['factory']]
                        if tradeInfoLp0['inToken'] < tradeInfoLp0['outToken']:
                            tradeInfoLp0['indexIn'] = 0
                        else:
                            tradeInfoLp0['indexIn'] = 1

                        tradeInfoLp1 = {}
                        tradeInfoLp1['lp'] = tradeLP1
                        tradeInfoLp1['inToken'] = tradeToken0
                        tradeInfoLp1['outToken'] = tradeToken1
                        tradeInfoLp1['fee'] = topFactoryFee[topLpInfo[tradeLP1]['factory']]
                        if tradeInfoLp1['inToken'] < tradeInfoLp1['outToken']:
                            tradeInfoLp1['indexIn'] = 0
                        else:
                            tradeInfoLp1['indexIn'] = 1

                        tradeInfoLp2 = {}
                        tradeInfoLp2['lp'] = tradeLP2
                        tradeInfoLp2['inToken'] = tradeToken1
                        tradeInfoLp2['outToken'] = endToken
                        tradeInfoLp2['fee'] = topFactoryFee[topLpInfo[tradeLP2]['factory']]
                        if tradeInfoLp2['inToken'] < tradeInfoLp2['outToken']:
                            tradeInfoLp2['indexIn'] = 0
                        else:
                            tradeInfoLp2['indexIn'] = 1

                        baseToken_endTokenArray.append([tradeInfoLp0, tradeInfoLp1, tradeInfoLp2])

    pushText(baseToken_endTokenArray, 'abca' + baseToken + endToken)


def pushABCA():
    for i in baseTokenInfo:
        i = i.lower()
        abca(i, i)
    abca(WETH, WETHW)
    abca(WETHW, WETH)


def readABCA():
    array = []
    for i in baseTokenInfo:
        i = i.lower()
        iiArray = readText('abca' + i + i)
        array = array + iiArray
    array = array + readText('abca' + WETHW + WETH)
    array = array + readText('abca' + WETH + WETHW)
    return array


def allUpdata():
    global topLpInfo
    topLPUpdata()
    topLpInfo = readText('topLP')
    printTime('Ture TOP LP', len(topLpInfo))
    pushABA()
    pushABCA()
    printTime(len(readABA()))
    printTime(len(readABCA()))
    lpRouterInfo = readABCA()
    lpRouterInfo = lpRouterInfo + readABA()
    pushText(lpRouterInfo, 'abcd')
    pushText(sharding_swap_path_list(lpRouterInfo), '256Router')


def calOnlyLpInRouterArray(routerArray):
    onlyLpArray = []
    for router in routerArray:
        for Lp in router:
            if Lp in onlyLpArray:
                continue
            onlyLpArray.append(Lp)
    return onlyLpArray


def sharding_swap_path_list(swap_path_list):
    swap_path_list_block = {}

    for swap_path in swap_path_list:
        for lp in swap_path:
            block = lp['lp']
            if block not in swap_path_list_block:
                swap_path_list_block[block] = []

            swap_path_list_block[block].append(json.loads(json.dumps(swap_path)))

    return swap_path_list_block


# {
# '0x00030110a7053083a7a160449a0e8f1adce9438d':
#   {'factory': '0x5c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f',
#   'token0': '0x65f9a292f1aeed5d755aa2fd2fb17ab2e9431447',
#   'token1': '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
#   'LP': '0x00030110a7053083a7a160449a0e8f1adce9438d'
#   }
# ....
# }]

while True:
    try:
        if time.time() % 60 < 5:
            allUpdata()
        time.sleep(3)
    except BaseException as err:
        printTime(traceback.format_exc())
        printTime('loop', err)
        time.sleep(20)
    

# printTime(len(readABA()))
# printTime(len(readABCA()))
# topLpInfo  = readText('topLP')
# lpRouterInfo = readABCA()
# lpRouterInfo = lpRouterInfo + readABA()

# printTime('find 0x9964ea0588e67a649b1333fe98d136db6e00d1be')
# routerArray = findLP('0x9964ea0588e67a649b1333fe98d136db6e00d1be', lpRouter)
# printTime('had find', len(routerArray))
# onlyLpArray = calOnlyLpInRouterArray(routerArray)
# printTime(onlyLpArray, len(onlyLpArray))
# lpResResult = (w3.dex.getPairSBalance(onlyLpArray))








