from pathlib import Path
import tempfile
import pickle

import pytest

from locan.analysis.pipeline import Pipeline, computation_test
from locan.analysis import metadata_analysis_pb2


def test_Pipeline(locdata_2d):
    with pytest.raises(TypeError):
        Pipeline()
    with pytest.raises(TypeError):
        Pipeline(computation=None, parameter='my_test')

    pipe = Pipeline(computation=computation_test, parameter='my_test')
    assert pipe
    assert isinstance(pipe.meta, metadata_analysis_pb2.AMetadata)
    assert pipe.kwargs == dict(parameter='my_test')
    pipe.compute()
    assert pipe.test == 'my_test'

    # this is not recommended since self.parameters are not updated automatically.
    computation_test(pipe, parameter='my_next_test')
    assert pipe.test == 'my_next_test'
    assert pipe.kwargs == dict(parameter='my_test')

    # several parameter including locdata reference and piped compute method.
    pipe = Pipeline(computation=computation_test, locdata=locdata_2d, parameter='my_test').compute()
    assert pipe.locdata is locdata_2d
    assert pipe.parameter['locdata'] is locdata_2d
    assert pipe.test == 'my_test'

    # print(pipe.computation_as_string())
    assert type(pipe.computation_as_string()) is str

    # save compute as text
    with tempfile.TemporaryDirectory() as tmp_directory:
        # for visual inspection use:
        # file_path = ROOT_DIR / 'tests/test_data/pipe.txt'
        file_path = Path(tmp_directory) / 'pipe.txt'
        pipe.save_computation(file_path)
        with open(file_path) as f:
            first_line = f.readline()
            assert first_line == "Analysis Pipeline: Pipeline\n"

    # pickling
    with tempfile.TemporaryDirectory() as tmp_directory:
        file_path = Path(tmp_directory) / 'pickled_pipeline.pickle'
        with open(file_path, 'wb') as file:
            pickle.dump(pipe, file, pickle.HIGHEST_PROTOCOL)
        with open(file_path, 'rb') as file:
            pipe_pickled = pickle.load(file)
        assert len(pipe_pickled.parameter) == len(pipe.parameter)
        assert isinstance(pipe_pickled.meta, metadata_analysis_pb2.AMetadata)
        assert pipe_pickled.meta == pipe.meta
        assert pipe_pickled.test == 'my_test'
