#!/usr/bin/env python3
# @file testDIO.py
#
# @brief Check all ports of the boards
#
# @author Manuel Castilla
# @date 25/04/2019
#
# Copyright (c) 2019 CERN (www.cern.ch).
#
# This file is part of WR Starting Kit project
# (see https://www.ohwr.org/project/wr-starting-kit).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
#(at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
###########################################################################

import configparser
from dio import DIO
import time

maxOffset = 0.000000017 #offset 17 nanoseconds


def findTimestamp(listStamp1,listStamp2,offset):
    """
    This function compare two list and search if two timestamps match

    Args:
        listStamp1: first list of timestamps
        listStamp2: second list of timestamps
        offset: maximum offset between each comparison

    Return:
        True if it find a match in the two lists, False otherwise
    """
    for i in listStamp1:
        for j in listStamp2:
            value = i - j
            if (value <= offset and value >= -offset):
                return True

    return False

def tryChannel(hostName1,userName1,password1,busId1,hostName2,userName2,password2,busId2,channel):
    """
    Try the input and output of channel

    Args:
        hostName1: ip remote host 1
        username1: user name host 1
        password1: password
        busId1: number PCIe bus PC 1
        hostName2: ip remote host 2
        username2: user name host 2
        password2: password
        busId2: number PCIe bus PC 2
        channel: number of channel to try(0 to 4)
    Return:
        True if the channel fail, False otherwise
    """
    try:
        dio1 = DIO(hostName1,userName1,password1,busId1)
        dio2 = DIO(hostName2,userName2,password2,busId2)
        dio1.configurePorts("pdddd")
        dio2.configurePorts("iiiii")
        dio1.clearTimestamps()
        dio2.clearTimestamps()

        if (channel != 0):
            dio1.armPulse(channel,0.1,"now")
        else:
            time.sleep(2) #wait 2 seconds to ensure some timestamp

        if(findTimestamp(dio1.getTimestamp(channel),dio2.getTimestamp(channel),maxOffset)):
            dio1.configurePorts("iiiii")
            dio2.configurePorts("pdddd")
            dio1.clearTimestamps()
            dio2.clearTimestamps()

            if (channel != 0):
                dio2.armPulse(channel,0.1,"now")
            else:
                time.sleep(2) #wait 2 seconds to ensure some timestamp

            if(findTimestamp(dio1.getTimestamp(channel),dio2.getTimestamp(channel),maxOffset)):
                print("Channel",channel,": ok in host:",hostName1,"and host:",hostName2)
                return False
            else:
                raise
        else:
            raise
    except:
        print("Channel",channel,": error in host:",hostName1,"or host:",hostName2)
        return True


#--------------------------------------------------#
#--------------------------------------------------#
# MAIN
#--------------------------------------------------#
#--------------------------------------------------#

def main(configuration):
    hostName1 = configuration["hostName1"]
    userName1 = configuration["userName1"]
    password1 = configuration["password1"]
    busIdSpec1 = configuration["busIdSpec1"]
    hostName2 = configuration["hostName2"]
    userName2 = configuration["userName2"]
    password2 = configuration["password2"]
    busIdSpec2 = configuration["busIdSpec2"]

    error = False
    numberChannels = 5

    print("\nExecuting DIO test")
    print("This test needs White Rabbit working")
    for i in range(numberChannels):
        error |= tryChannel(hostName1,userName1,password1,busIdSpec1,hostName2,userName2,password2,busIdSpec2,i)

    if(not error):
        print("Test DIO: successful")
    else:
        print("Test DIO: error")

if __name__ == '__main__':
    try:
        configuration = {}
        nameConfig = "configuration.cfg"

        config = configparser.ConfigParser()
        config.readfp(open(nameConfig))

        configuration["hostName1"] = config.get('pc1',"hostName")
        configuration["userName1"] = config.get('pc1',"userName")
        configuration["password1"] = config.get('pc1',"password")
        configuration["busIdSpec1"] = config.get('pc1',"busIdSpec")
        configuration["hostName2"] = config.get('pc2',"hostName")
        configuration["userName2"] = config.get('pc2',"userName")
        configuration["password2"] = config.get('pc2',"password")
        configuration["busIdSpec2"] = config.get('pc2',"busIdSpec")

        main(configuration)
    except configparser.Error as e:
        print("Error load configuration:",e.message)
