#   Copyright ETH 2019 - 2024 Zürich, Scientific IT Services
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
#

import time
import uuid

import pytest


def test_create_delete_plugin(openbis_instance):
    timestamp = time.strftime('%a_%y%m%d_%H%M%S').upper()
    pl_name = 'test_plugin_' + timestamp

    plugin = openbis_instance.new_plugin(
	name= pl_name,
	pluginType='ENTITY_VALIDATION',   # or 'DYNAMIC_PROPERTY' or 'MANAGED_PROPERTY',
	entityKind = None,                # or 'SAMPLE', 'MATERIAL', 'EXPERIMENT', 'DATA_SET'
	script = 'def calculate(): pass'  # JYTHON script
    )

    with pytest.raises(ValueError):
        plugin.pluginType = 'Rubbish'
        assert 1 == 0

    with pytest.raises(ValueError):
        plugin.entityKind = 'even more Rubbish'
        assert 1 == 0

    plugin.save()
    pl_exists = openbis_instance.get_plugin(pl_name)
    assert pl_exists is not None

    plugin.delete("test on {}".format(timestamp))

    with pytest.raises(ValueError):
        pl_not_exists = openbis_instance.get_plugin(plugin.name)
        assert pl_not_exists is None


def test_search_plugins(openbis_instance):
    plugins = openbis_instance.get_plugins(start_with=1, count=1)
    assert len(plugins) == 1
    assert plugins.df.__class__.__name__ == 'DataFrame'
    assert len(plugins) == len(plugins.df)

    plugin = plugins[0]
    assert plugin.__class__.__name__ == 'Plugin'


def test_assign_plugin_to_sample_type(openbis_instance):

    timestamp = time.strftime("%a_%y%m%d_%H%M%S").upper()

    plugin_name = 'TEST.NEW_PLUGIN_' + timestamp + "_" + str(uuid.uuid4())
    pl = openbis_instance.new_plugin(
        name=plugin_name,
        pluginType='DYNAMIC_PROPERTY',
        entityKind='SAMPLE',
        script='def validate(x, True):\n\treturn "OK"'
    )
    pl.save()

    sample_type_code = 'SOME_TEST_SAMPLE_TYPE_' + timestamp + "_" + str(uuid.uuid4())
    sample_type = openbis_instance.new_sample_type(
        code=sample_type_code,
        generatedCodePrefix='STST-',
        autoGeneratedCode=True
    )
    sample_type.save()

    sample_type = openbis_instance.get_sample_type(sample_type_code)
    assignments = sample_type.get_property_assignments().df

    assert len(assignments) == 0

    property_code = 'SOME_TEST_PROPERTY_' + timestamp + "_" + str(uuid.uuid4())
    prop_type = openbis_instance.new_property_type(
        code=property_code,
        label='test property',
        description='test property',
        dataType='VARCHAR',
    )
    prop_type.save()

    sample_type.assign_property(prop_type, section='General info', ordinal=2,
                                initialValueForExistingEntities='', plugin=plugin_name)

    assignments = sample_type.get_property_assignments().df

    assert len(assignments) == 1
    assert assignments.loc[0]['plugin'] == plugin_name

    sample = openbis_instance.new_sample(
        type=sample_type.code,
        space='DEFAULT',
        experiment='/DEFAULT/DEFAULT/DEFAULT',
        props={property_code.lower(): "some_value"}
    )
    sample.save()

    sample_type.revoke_property(property_code, force=True)

    assignments = sample_type.get_property_assignments().df
    assert len(assignments) == 0


def test_update_plugin(openbis_instance):
    timestamp = time.strftime('%a_%y%m%d_%H%M%S').upper()
    pl_name = 'test_plugin_' + timestamp

    plugin = openbis_instance.new_plugin(
        name=pl_name,
        pluginType='ENTITY_VALIDATION',  # or 'DYNAMIC_PROPERTY' or 'MANAGED_PROPERTY',
        entityKind=None,  # or 'SAMPLE', 'MATERIAL', 'EXPERIMENT', 'DATA_SET'
        script='def calculate(): pass'  # JYTHON script
    )
    plugin.save()
    pl_exists = openbis_instance.get_plugin(pl_name)
    assert pl_exists is not None

    plugin.description = 'some boring description'
    plugin.available = True
    plugin.script = 'def calculate(): fail'
    plugin.save()

    pl_exists = openbis_instance.get_plugin(pl_name)
    assert pl_exists is not None
    assert pl_exists.description == 'some boring description'
    assert pl_exists.script == 'def calculate(): fail'
    assert pl_exists.available is True

