
import taos
import sys
import time
import socket
import pexpect
import os

from util.log import *
from util.sql import *
from util.cases import *
from util.dnodes import *

def taos_command (buildPath, key, value, expectString, cfgDir, sqlString='', key1='', value1=''):
    if len(key) == 0:
        tdLog.exit("taos test key is null!")
    
    taosCmd = buildPath + '/build/bin/taos '
    if len(cfgDir) != 0:
        taosCmd = taosCmd + '-c ' + cfgDir

    taosCmd = taosCmd + ' -' + key
    if len(value) != 0:
        if key == 'p':
            taosCmd = taosCmd + value
        else:
            taosCmd = taosCmd + ' ' + value

    if len(key1) != 0:
        taosCmd = taosCmd + ' -' + key1
        if key1 == 'p':
            taosCmd = taosCmd + value1
        else:
            if len(value1) != 0:
                taosCmd = taosCmd + ' ' + value1

    tdLog.info ("taos cmd: %s" % taosCmd)

    child = pexpect.spawn(taosCmd, timeout=3)
    #output = child.readline()
    #print (output.decode())
    if len(expectString) != 0:
        i = child.expect([expectString, pexpect.TIMEOUT, pexpect.EOF], timeout=6)
    else:
        i = child.expect([pexpect.TIMEOUT, pexpect.EOF], timeout=6)

    retResult = child.before.decode()
    print("expect() return code: %d, content:\n %s\n"%(i, retResult))
    #print(child.after.decode())
    if i == 0:
        print ('taos login success! Here can run sql, taos> ')
        if len(sqlString) != 0:
            child.sendline (sqlString)
            w = child.expect(["Query OK", pexpect.TIMEOUT, pexpect.EOF], timeout=1)
            retResult = child.before.decode()
            if w == 0:
                return "TAOS_OK", retResult
            else:
                return "TAOS_FAIL", retResult
        else:
            if key == 'A' or key1 == 'A' or key == 'C' or key1 == 'C' or key == 'V' or key1 == 'V':
                return "TAOS_OK", retResult
            else:
                return  "TAOS_OK", retResult
    else:
        if key == 'A' or key1 == 'A' or key == 'C' or key1 == 'C' or key == 'V' or key1 == 'V':
            return "TAOS_OK", retResult
        else:
            return "TAOS_FAIL", retResult

class TDTestCase:
    #updatecfgDict = {'clientCfg': {'serverPort': 7080, 'firstEp': 'trd02:7080', 'secondEp':'trd02:7080'},\
    #                 'serverPort': 7080, 'firstEp': 'trd02:7080'}
    hostname = socket.gethostname()
    serverPort = '7080'
    rpcDebugFlagVal = '143'
    clientCfgDict = {'serverPort': '', 'firstEp': '', 'secondEp':'', 'rpcDebugFlag':'135', 'fqdn':''}
    clientCfgDict["serverPort"]    = serverPort
    clientCfgDict["firstEp"]       = hostname + ':' + serverPort
    clientCfgDict["secondEp"]      = hostname + ':' + serverPort
    clientCfgDict["rpcDebugFlag"]  = rpcDebugFlagVal
    clientCfgDict["fqdn"] = hostname

    updatecfgDict = {'clientCfg': {}, 'serverPort': '', 'firstEp': '', 'secondEp':'', 'rpcDebugFlag':'135', 'fqdn':''}
    updatecfgDict["clientCfg"]  = clientCfgDict
    updatecfgDict["serverPort"] = serverPort
    updatecfgDict["firstEp"]    = hostname + ':' + serverPort
    updatecfgDict["secondEp"]   = hostname + ':' + serverPort
    updatecfgDict["fqdn"] = hostname

    print ("===================: ", updatecfgDict)

    def init(self, conn, logSql):
        tdLog.debug(f"start to excute {__file__}")
        tdSql.init(conn.cursor())

    def getBuildPath(self):
        selfPath = os.path.dirname(os.path.realpath(__file__))

        if ("community" in selfPath):
            projPath = selfPath[:selfPath.find("community")]
        else:
            projPath = selfPath[:selfPath.find("tests")]

        for root, dirs, files in os.walk(projPath):
            if ("taosd" in files):
                rootRealPath = os.path.dirname(os.path.realpath(root))
                if ("packaging" not in rootRealPath):
                    buildPath = root[:len(root) - len("/build/bin")]
                    break
        return buildPath

    def run(self):  # sourcery skip: extract-duplicate-method, remove-redundant-fstring
        tdSql.prepare()
        tdSql.query("create user testpy pass 'testpy'")

        buildPath = self.getBuildPath()
        if (buildPath == ""):
            tdLog.exit("taosd not found!")
        else:
            tdLog.info("taosd found in %s" % buildPath)
        cfgPath = buildPath + "/../sim/psim/cfg"
        tdLog.info("cfgPath: %s" % cfgPath)

        checkNetworkStatus = ['0: unavailable', '1: network ok', '2: service ok', '3: service degraded', '4: exiting']
        netrole            = ['client', 'server']

        keyDict = {'h':'', 'P':'6030', 'p':'testpy', 'u':'testpy', 'a':'', 'A':'', 'c':'', 'C':'', 's':'', 'r':'', 'f':'', \
                   'k':'', 't':'', 'n':'', 'l':'1024', 'N':'100', 'V':'', 'd':'db', 'w':'30', '-help':'', '-usage':'', '?':''}

        keyDict['h'] = self.hostname
        keyDict['c'] = cfgPath
        keyDict['P'] = self.serverPort

        tdLog.printNoPrefix("================================ parameter: -k")
        sqlString = ''
        retCode, retVal = taos_command(buildPath, "k", '', "", keyDict['c'], sqlString)
        if "2: service ok" in retVal:
            tdLog.info("taos -k success")
        else:
            tdLog.exit("taos -k fail")

        # stop taosd
        tdDnodes.stop(1)
        #sleep(10)
        #tdDnodes.start(1)
        #sleep(5) 
        retCode, retVal = taos_command(buildPath, "k", '', "", keyDict['c'], sqlString)
        if "0: unavailable" in retVal:
            tdLog.info("taos -k success")
        else:
            tdLog.exit("taos -k fail")

        # restart taosd
        tdDnodes.start(1)
        #sleep(5) 
        retCode, retVal = taos_command(buildPath, "k", '', "", keyDict['c'], sqlString)
        if "2: service ok" in retVal:
            tdLog.info("taos -k success")
        else:
            tdLog.exit("taos -k fail")

        tdLog.printNoPrefix("================================ parameter: -n")
        # stop taosd
        tdDnodes.stop(1)        

        role   = 'server'
        taosCmd = 'nohup ' + buildPath + '/build/bin/taos -c ' + keyDict['c']
        taosCmd = taosCmd + ' -n ' + role + ' > /dev/null 2>&1 &'
        print (taosCmd)
        os.system(taosCmd)

        pktLen = '2000'
        pktNum = '10'
        role   = 'client'
        taosCmd = buildPath + '/build/bin/taos -c ' + keyDict['c']
        taosCmd = taosCmd + ' -n ' + role + ' -l ' + pktLen + ' -N ' +  pktNum
        print (taosCmd)
        child = pexpect.spawn(taosCmd, timeout=3)
        i = child.expect([pexpect.TIMEOUT, pexpect.EOF], timeout=6)

        retResult = child.before.decode()
        print("expect() return code: %d, content:\n %s\n"%(i, retResult))
        #print(child.after.decode())
        if i == 0:
            tdLog.exit('taos -n server fail!')
        
        expectString1 = 'response is received, size:' + pktLen
        expectSTring2 = pktNum + '/' + pktNum
        if expectString1 in retResult and expectSTring2 in retResult:
            tdLog.info("taos -n client success")
        else:
            tdLog.exit('taos -n client fail!')

        os.system('pkill taos')

    def stop(self):
        tdSql.close()
        tdLog.success(f"{__file__} successfully executed")

tdCases.addLinux(__file__, TDTestCase())
tdCases.addWindows(__file__, TDTestCase())
