"""
B-ASIC test suite for load/save datastructures.
"""

from os import getcwd, path
from random import choice
from string import ascii_lowercase

import pytest

from b_asic import SFG, Output, load_structure, save_structure, load_recipe


class TestSaveStructures:

    def test_save_sfg(self, large_operation_tree):
        sfg = SFG(outputs=[Output(large_operation_tree)])
        _path = save_structure(sfg)
    
        assert _path is not None
        assert path.isfile(_path)

    def test_load_sfg(self, large_operation_tree):
        sfg = SFG(outputs=[Output(large_operation_tree)])
        _path = save_structure(sfg)
        _sfg = load_structure(_path)
        
        assert isinstance(_sfg, SFG)
        assert sorted([comp.type_name for comp in _sfg.components]) == sorted([comp.type_name for comp in sfg.components])
        assert sfg.evaluate() == _sfg.evaluate()

    def test_save_invalid_path(self, large_operation_tree):
        sfg = SFG(outputs=[Output(large_operation_tree)])
        
        _folder = "".join(choice(ascii_lowercase) for _ in range(4))
        while path.exists(path.join(getcwd(), _folder)):
            _folder = "".join(choice(ascii_lowercase) for _ in range(4))

        _invalid_path = path.join(getcwd(), _folder, "cool.pickle") 
        _path = save_structure(sfg, _path=_invalid_path)

        assert _path is None

    def test_load_invalid_path(self, large_operation_tree):
        _folder = "".join(choice(ascii_lowercase) for _ in range(4))
        while path.exists(path.join(getcwd(), _folder)):
            _folder = "".join(choice(ascii_lowercase) for _ in range(4))

        _invalid_path = path.join(getcwd(), _folder, "cool.pickle") 
        _path = load_structure(_path=_invalid_path)

        assert _path is None 
    
    def test_load_recipe_file(self):
        # Create a file that doesn't exist
        _file = "".join(choice(ascii_lowercase) for _ in range(4)) + ".py"
        while path.exists(path.join(getcwd(), _file)):
            _file = "".join(choice(ascii_lowercase) for _ in range(4)) + ".py"

        try:
            with open(_file, "w+") as handle:
                # The string is indented that way so the file is properly indented, .strip() did not work idk why
                handle.write(
"""
from b_asic import SFG, Output, Addition, Constant
sfg = SFG(outputs=[Output(Addition(Addition(Constant(2), Constant(3)), Addition(Constant(4), Constant(5))))])
"""
                )
        except Exception as e:
            assert False, f"Could not create file: {e}"

        # Not defined yet
        with pytest.raises(NameError):
            sfg.evaluate() == 14

        load_recipe(_file)
        assert sfg.evaluate() == 14

    def test_load_invalid_recipe_file(self):
        _file = "".join(choice(ascii_lowercase) for _ in range(4)) + ".py"
        while path.exists(path.join(getcwd(), _file)):
            _file = "".join(choice(ascii_lowercase) for _ in range(4)) + ".py"

        load_recipe(_file)
        with pytest.raises(NameError):
            assert sfg.evaluate() == 14