from fabrictestbed_extensions.fablib.attestable_switch import Attestable_Switch
from fabrictestbed_extensions.fablib.fablib import FablibManager as fablib_manager
from ipaddress import ip_address, IPv4Address, IPv4Network
from concurrent import futures
from datetime import datetime
from . import custom_setup


# hosts = [h11, h12, h13, h14, h21, h22, h31, h32, h33, h41, h42]
# switches = [s11, s12, s21, s31, s32, s41, s42]
# routers = [r1, r2, r3, r4]

def run_baseline(vslice, macs, ips, subnets, hosts, routers):

    table_host = "table_host"
    table_internet = "table_internet"
    forward_host = "forward"
    forward_router = "forward"
    file_r1 = "scripts/rules_r1.txt"
    file_r2 = "scripts/rules_r2.txt"
    file_r3 = "scripts/rules_r3.txt"
    file_r4 = "scripts/rules_r4.txt"
    file_r5 = "scripts/rules_r5.txt"
    file_r6 = "scripts/rules_r6.txt"
    file_r7 = "scripts/rules_r7.txt"
    file_r8 = "scripts/rules_r8.txt"
    file_r9 = "scripts/rules_r9.txt"
    files = {
        "r1": file_r1,
        "r2": file_r2,
        "r3": file_r3,
        "r4": file_r4,
        "r5": file_r5,
        "r6": file_r6,
        "r7": file_r7,
        "r8": file_r8,
        "r9": file_r9
    }
        
    with open(file_r1, 'w') as outfile:
        outfile.write("load_new_config_file router-1.json\n")
        outfile.write("swap_configs\n")
        for i in range(3):
            outfile.write(f"table_add {table_host} {forward_host} {ips['h1'][0]} 0 {i} => {macs['h1'][0]} {macs['r1'][2]} 2\n")
            outfile.write(f"table_add {table_host} {forward_host} {ips['h1'][0]} 1 {i} => {macs['h1'][0]} {macs['r1'][2]} 2\n")
            if i == 1:
                outfile.write(f"table_add {table_internet} {forward_router} {subnets['h2'][0]} 2 {i} => {macs['r2'][1]} {macs['r1'][0]} 0\n")
            else:
                outfile.write(f"table_add {table_internet} {forward_router} {subnets['h2'][0]} 2 {i} => {macs['r8'][0]} {macs['r1'][1]} 1\n")
        
    with open(file_r2, 'w') as outfile:
        outfile.write("load_new_config_file router-1.json\n")
        outfile.write("swap_configs\n")
        for i in range(3):
            outfile.write(f"table_add {table_internet} {forward_router} {subnets['h1'][0]} 0 {i} => {macs['r1'][0]} {macs['r2'][1]} 1\n")
            outfile.write(f"table_add {table_internet} {forward_router} {subnets['h1'][0]} 2 {i} => {macs['r1'][0]} {macs['r2'][1]} 1\n")
            outfile.write(f"table_add {table_internet} {forward_router} {subnets['h2'][0]} 2 {i} => {macs['r3'][1]} {macs['r2'][0]} 0\n")
            if i == 1:
                outfile.write(f"table_add {table_internet} {forward_router} {subnets['h2'][0]} 1 {i} => {macs['r9'][0]} {macs['r2'][2]} 2\n")
            else:
                outfile.write(f"table_add {table_internet} {forward_router} {subnets['h2'][0]} 1 {i} => {macs['r3'][1]} {macs['r2'][0]} 0\n")
        
    with open(file_r3, 'w') as outfile:
        outfile.write("load_new_config_file router-1.json\n")
        outfile.write("swap_configs\n")
        for i in range(3):
            outfile.write(f"table_add {table_internet} {forward_router} {subnets['h2'][0]} 1 {i} => {macs['r4'][1]} {macs['r3'][0]} 0\n")
            outfile.write(f"table_add {table_internet} {forward_router} {subnets['h1'][0]} 0 {i} => {macs['r2'][0]} {macs['r3'][1]} 1\n")
        
    with open(file_r4, 'w') as outfile:
        outfile.write("load_new_config_file router-1.json\n")
        outfile.write("swap_configs\n")
        for i in range(3):
            outfile.write(f"table_add {table_internet} {forward_router} {subnets['h2'][0]} 1 {i} => {macs['r5'][1]} {macs['r4'][0]} 0\n")
            outfile.write(f"table_add {table_internet} {forward_router} {subnets['h2'][0]} 2 {i} => {macs['r5'][1]} {macs['r4'][0]} 0\n")
            outfile.write(f"table_add {table_internet} {forward_router} {subnets['h1'][0]} 2 {i} => {macs['r3'][0]} {macs['r4'][1]} 1\n")
            if i == 1:
                outfile.write(f"table_add {table_internet} {forward_router} {subnets['h1'][0]} 0 {i} => {macs['r9'][1]} {macs['r4'][2]} 2\n")
            else:
                outfile.write(f"table_add {table_internet} {forward_router} {subnets['h1'][0]} 0 {i} => {macs['r3'][0]} {macs['r4'][1]} 1\n")
        
    with open(file_r5, 'w') as outfile:
        outfile.write("load_new_config_file router-1.json\n")
        outfile.write("swap_configs\n")
        for i in range(3):
            outfile.write(f"table_add {table_host} {forward_host} {ips['h2'][0]} 0 {i} => {macs['h2'][0]} {macs['r1'][2]} 2\n")
            outfile.write(f"table_add {table_host} {forward_host} {ips['h2'][0]} 1 {i} => {macs['h2'][0]} {macs['r1'][2]} 2\n")
            if i == 1:
                outfile.write(f"table_add {table_internet} {forward_router} {subnets['h1'][0]} 2 {i} => {macs['r6'][1]} {macs['r1'][0]} 0\n")
            else:
                outfile.write(f"table_add {table_internet} {forward_router} {subnets['h1'][0]} 2 {i} => {macs['r4'][0]} {macs['r1'][1]} 1\n")
        
    with open(file_r6, 'w') as outfile:
        outfile.write("load_new_config_file router-1.json\n")
        outfile.write("swap_configs\n")
        for i in range(3):
            outfile.write(f"table_add {table_internet} {forward_router} {subnets['h2'][0]} 0 {i} => {macs['r5'][0]} {macs['r6'][1]} 1\n")
            outfile.write(f"table_add {table_internet} {forward_router} {subnets['h2'][0]} 2 {i} => {macs['r5'][0]} {macs['r6'][1]} 1\n")
            outfile.write(f"table_add {table_internet} {forward_router} {subnets['h1'][0]} 2 {i} => {macs['r7'][1]} {macs['r6'][0]} 0\n")
            if i == 1:
                outfile.write(f"table_add {table_internet} {forward_router} {subnets['h1'][0]} 1 {i} => {macs['r9'][2]} {macs['r6'][2]} 2\n")
            else:
                outfile.write(f"table_add {table_internet} {forward_router} {subnets['h1'][0]} 1 {i} => {macs['r7'][1]} {macs['r6'][0]} 0\n")
        
    with open(file_r7, 'w') as outfile:
        outfile.write("load_new_config_file router-1.json\n")
        outfile.write("swap_configs\n")
        for i in range(3):
            outfile.write(f"table_add {table_internet} {forward_router} {subnets['h2'][0]} 0 {i} => {macs['r6'][0]} {macs['r7'][1]} 1\n")
            outfile.write(f"table_add {table_internet} {forward_router} {subnets['h1'][0]} 1 {i} => {macs['r8'][1]} {macs['r7'][0]} 0\n")
        
    with open(file_r8, 'w') as outfile:
        outfile.write("load_new_config_file router-1.json\n")
        outfile.write("swap_configs\n")
        for i in range(3):
            outfile.write(f"table_add {table_internet} {forward_router} {subnets['h1'][0]} 1 {i} => {macs['r1'][1]} {macs['r8'][0]} 0\n")
            outfile.write(f"table_add {table_internet} {forward_router} {subnets['h1'][0]} 2 {i} => {macs['r1'][1]} {macs['r8'][0]} 0\n")
            outfile.write(f"table_add {table_internet} {forward_router} {subnets['h2'][0]} 2 {i} => {macs['r7'][0]} {macs['r8'][1]} 1\n")
            if i == 1:
                outfile.write(f"table_add {table_internet} {forward_router} {subnets['h2'][0]} 0 {i} => {macs['r9'][3]} {macs['r8'][2]} 2\n")
            else:
                outfile.write(f"table_add {table_internet} {forward_router} {subnets['h2'][0]} 0 {i} => {macs['r7'][0]} {macs['r8'][1]} 1\n")
        
    with open(file_r9, 'w') as outfile:
        outfile.write("load_new_config_file router-1.json\n")
        outfile.write("swap_configs\n")
        for i in range(3):
            for hostname in ['h1', 'h2']:
                if i == 1:
                    outfile.write(f"table_add {table_internet} {forward_router} {subnets[hostname][0]} 0 {i} => {macs['r4'][2]} {macs['r9'][1]} 1\n")
                    outfile.write(f"table_add {table_internet} {forward_router} {subnets[hostname][0]} 1 {i} => {macs['r6'][2]} {macs['r9'][2]} 2\n")
                    outfile.write(f"table_add {table_internet} {forward_router} {subnets[hostname][0]} 2 {i} => {macs['r4'][2]} {macs['r9'][1]} 1\n")
                    outfile.write(f"table_add {table_internet} {forward_router} {subnets[hostname][0]} 3 {i} => {macs['r4'][2]} {macs['r9'][1]} 1\n")
                else:
                    outfile.write(f"table_add {table_internet} {forward_router} {subnets[hostname][0]} 0 {i} => {macs['r6'][2]} {macs['r9'][2]} 2\n")
                    outfile.write(f"table_add {table_internet} {forward_router} {subnets[hostname][0]} 1 {i} => {macs['r6'][2]} {macs['r9'][2]} 2\n")
                    outfile.write(f"table_add {table_internet} {forward_router} {subnets[hostname][0]} 2 {i} => {macs['r4'][2]} {macs['r9'][1]} 1\n")
                    outfile.write(f"table_add {table_internet} {forward_router} {subnets[hostname][0]} 3 {i} => {macs['r6'][2]} {macs['r9'][2]} 2\n")

    jobs = []
    for routername, router in routers.items():
        jobs.append(router.upload_file_thread(files[routername], "/home/ubuntu/rules.txt"))
    futures.wait(jobs)
    jobs = []
    for routername, router in routers.items():
        jobs.append(router.execute_thread(f"cat rules.txt | simple_switch_CLI"))
    futures.wait(jobs)
    
    overall = True
    pingtest = False
    h1 = hosts['h1']
    print('h1 pinging h2 20 times')
    failed = []
    for i in range(20):
        print(f"[{datetime.now()}] hosts['h1'].ping_test(ips['h2'][0])...", end="")
        pingtest = h1.ping_test(ips['h2'][0])
        if pingtest:
            print("True")
        else:
            overall = False
            failed.append(i)
            print("False")

    if not overall:
        print("Baseline failed - Try running it again.\nIf it fails again, please try rerunning the setup command with:")
        print("  do_install=True, if 'Finished installing needed tools' did not print or if the issue is p4c is not installed on nodes")
        print("  conf_ifaces=True, if there is no p4c error but the baseline pings fail")
        print("If the issue persists, please delete and rebuild the slice.")
    else:
        print("Baseline test passed.")
    return overall















