#!/usr/bin/python3
# MAmas TEsting System
# Copyright (c) Jan Otte, Dwarf Technologies s.r.o. All rights reserved.

# NOTE: MATES has not been used for a while. The script may need some update before is starts to be used in automatic testing heavily
# TODO: update for device_token handling (should be stored in devicepool already but needs to be passed to push_data and other functions
# FIXME: see results from make pycheck - mates needs to b updated with machine IDs etc.
#************* Module mates
#test/mates.py:75:7: E1120: No value for argument 'machine_id' in function call (no-value-for-parameter)
#test/mates.py:75:7: E1120: No value for argument 'device_token' in function call (no-value-for-parameter)
#test/mates.py:75:7: E1120: No value for argument 'iccid' in function call (no-value-for-parameter)
#test/mates.py:75:7: E1120: No value for argument 'dict_keep' in function call (no-value-for-parameter)
#test/mates.py:99:27: E1120: No value for argument 'machine_id' in function call (no-value-for-parameter)
#test/mates.py:99:27: E1120: No value for argument 'device_token' in function call (no-value-for-parameter)
#test/mates.py:99:27: E1120: No value for argument 'iccid' in function call (no-value-for-parameter)
#test/mates.py:99:27: E1120: No value for argument 'dict_keep' in function call (no-value-for-parameter)
#test/mates.py:108:7: E1120: No value for argument 'machine_id' in function call (no-value-for-parameter)
#test/mates.py:108:7: E1120: No value for argument 'device_token' in function call (no-value-for-parameter)
#test/mates.py:108:7: E1120: No value for argument 'iccid' in function call (no-value-for-parameter)
#test/mates.py:108:7: E1120: No value for argument 'dict_keep' in function call (no-value-for-parameter)
#test/mates.py:114:7: E1120: No value for argument 'machine_id' in function call (no-value-for-parameter)
#test/mates.py:114:7: E1120: No value for argument 'device_token' in function call (no-value-for-parameter)
#test/mates.py:114:7: E1120: No value for argument 'iccid' in function call (no-value-for-parameter)
#test/mates.py:114:7: E1120: No value for argument 'dict_keep' in function call (no-value-for-parameter)



import time
import matelib as mt
import dwarfg_lib as maml

devicepool=[]
db_devcount=0

def tff_stopstart(arg = None):
    if mt.mamas_check():
        mt.mamas_stop()
        stop_done = True, None
    else:
        stop_done = False, None
    if mt.mamas_start() and (stop_done or (mt.mamas_stop() and mt.mamas_start())):
        return True, None
    return False, "Unable to start mamasd."

def tff_dbinit(arg = None):
    global db_devcount
    if mt.mdb_connect():
        db_devcount = mt.mdb_get_devicecount()
        if 0<=db_devcount:
            return True, None
        else:
            return False, "Device count is < 0 (" + str(db_devcount) + ")"
    return False, "Cannot connect to the DB"

def tff_dbclose(arg = None):
    if mt.mdb_disconnect():
        return True, None
    return False, "Cannot close DB connection"

def tff_regone(arg = None):
    global devicepool
    global db_devcount
    if mt.register(devicepool):
        time.sleep(30)
        newdbd = mt.mdb_get_devicecount()
        if newdbd == db_devcount+1:
            db_devcount = newdbd
            return True, None
        else:
            return False, "Device count expected to increment from " + str(db_devcount) + " to " + str(1+db_devcount) + " but it is " + str(newdbd)
    return False, "Failed to register device"

def tff_datapush_def(idx = -1):
    devd = mt.mdb_get_device(devicepool[idx][0])
    if mt.push_data(devicepool[idx][0], devicepool[idx][1]):
        time.sleep(30)
        devd_new = mt.mdb_get_device(devicepool[idx][0])
        if devd != devd_new:
            return True, None
        else:
            return False, "No change in data for device " + mt.devid_str(devicepool[idx][0]) + " has been detected"
    return False, "Data push for device " + mt.devid_str(devicepool[idx][0]) + " failed"

def tff_apprfw620(idx = -1):
    if not mt.mdb_set_fwver(4, 1):
        return False, "Unable to set FW version 4 as aproved"
    # check if update needed
    time.sleep(30)
    return True, None

def tff_setdevfwdesver620(idx = -1):
    if not mt.mdb_set_device(maml.pathstringtonum(devicepool[idx][0]), 4, None):
        return False, "Unable to set device " + mt.devid_str(devicepool[idx][0]) + " desired FW version to 4"
    time.sleep(5)
    return True, None

def tff_fetchfwupd620(idx = -1):
    time.sleep(60)
    (ret, code, content) = mt.push_data(devicepool[idx][0], devicepool[idx][1])
    mt.tprint(content)
    if not ret or 0 != code:
        return False, "Data push for device " + mt.devid_str(devicepool[idx][0]) + " failed or resulted with non-zero code: " + str(code)
    if not mt.comparefilo(content, mt.getfilo("fwupg620_rcv1")):
        return False, "Data push resulting data differs from " + mt.getfilo("fwupg620_rcv1")
    return True, None

def tff_datapush_fw625(idx = -1):
    if mt.push_data(devicepool[idx][0], devicepool[idx][1], datafname="rout1fw625"):
        time.sleep(30)
        return True, None
    return False, "Data push for device " + mt.devid_str(devicepool[idx][0]) + " failed"

def tff_datapush_fw620(idx = -1):
    if mt.push_data(devicepool[idx][0], devicepool[idx][1], datafname="rout1fw620"):
        time.sleep(30)
        return True, None
    return False, "Data push for device " + mt.devid_str(devicepool[idx][0]) + " failed"

def tff_check_noupdneeded(idx = -1):
    if mt.mdb_device_toupdate(devicepool[idx][0]):
        return False, "Device " + mt.devid_str(devicepool[idx][0]) + " still has data to update."
    return True, None

testreg =("Register one device", [
    (tff_stopstart, None),
    (tff_dbinit, None),
    (tff_regone, None),
    (tff_dbclose, None)
    ])
testpush=("Push data for one device", [
    (tff_stopstart, None),
    (tff_dbinit, None),
    (tff_regone, None),
    (tff_datapush_def, -1),
    (tff_dbclose, None)
    ])
testfwup=("FW Upgrade test", [
    (tff_stopstart, None),
    (tff_dbinit, None),
    (tff_regone, None),
    (tff_datapush_fw625, -1),
    (tff_apprfw620, None),
    (tff_setdevfwdesver620, -1),
    (tff_fetchfwupd620, -1),
    (tff_datapush_fw620, -1),
    (tff_check_noupdneeded, -1),
    (tff_dbclose, None)
    ]) # TODO: improve by adding sync status change check
#testclone=("Test cloning cfg", [
#    (tff_stopstart, None),
#    (tff_dbinit, None),
#    (tff_regone, None),
#    (tff_regone, None),
#    (tff_datapush_def, 0),
#    (tff_datapush_def, 1),
#    (tff_cfgpush_cfg1, 0),
#    (tff_cfgpush_cfg2, 1),
#    (tff_setclone
#        (ttf_datapush


def runner(testcase, runall = False):
    failcount = 0
    (tcname, funclist) = testcase
    print(" --- Testcase: ", tcname, " ---> ")
    for i in range(len(funclist)):
        print("Running test step no. ", str(i+1), ": ", funclist[i][0].__name__, " ... ", flush=True)
        (res, msg) = funclist[i][0](funclist[i][1])
        if not res:
            if msg:
                print(":::Test-step FAILURE: " + msg)
            else:
                print(":::Test-step FAILURE")
            if runall:
                failcount += 1
            else:
                return False
        else:
            print(":::Test-step SUCCESS")
    print("Passed: " + str(len(funclist)-failcount), "\nFailed: " + str(failcount))
    if 0 == failcount:
        print("<--- PASSED ---")
        return True
    print("<--- FAILED ---")
    return False

