import pytest
import os
from calculate.templates.template_engine import ParametersProcessor, DIR,\
                                                FILE, IncorrectParameter,\
                                                ParametersContainer
from calculate.templates.template_processor import TemplateExecutor
from calculate.utils.files import join_paths


CHROOT_PATH = os.path.join(
                    os.getcwd(),
                    'tests/templates/testfiles/test_parameters_processor_root')


parameters_processor = ParametersProcessor(chroot_path=CHROOT_PATH)
parameters_processor.available_appends = TemplateExecutor(
                                         cl_config_path=join_paths(
                                          CHROOT_PATH,
                                          'test_root/var/lib/calculate/config')
                                                         ).available_appends


@pytest.mark.parameters_processor
class TestTemplateParameters:
    def test_if_TemplateParameters_object_is_initialized_accoding_to_dictionary_of_correct_template_parameters__the_TemplateParameters_object_contains_processed_parameters_as_its_attributes_including_default_values(self):
        parameters = {'append': 'join',
                      'chmod': '600',
                      'force': True}

        parameters_object = ParametersContainer()
        parameters_processor.set_parameters_container(parameters_object)
        for parameter_name, parameter_value in parameters.items():
            parameters_processor.check_template_parameter(parameter_name,
                                                          parameter_value,
                                                          DIR, 1)

        parameters_processor.check_postparse_parameters()
        assert (parameters_object.append == 'join' and
                parameters_object.chmod == 0o600 and
                parameters_object.force and
                not parameters_object.autoupdate)

    def test_if_TemplateParameters_object_is_intialized_using_dictionary_with_append_parameter__a_value_of_the_parameter_will_be_checked(self):
        parameters = {'append': 'join'}

        parameters_object = ParametersContainer()
        parameters_processor.set_parameters_container(parameters_object)
        try:
            for parameter_name, parameter_value in parameters.items():
                parameters_processor.check_template_parameter(parameter_name,
                                                              parameter_value,
                                                              FILE, 1)
            parameters_processor.check_postparse_parameters()
        except Exception as error:
            pytest.fail('Unexpected exception: {0}'.
                        format(str(error)))

        assert parameters_object.append == 'join'

    def test_if_TemplateParameters_object_is_intialized_using_dictionary_with_correct_source_parameter__the_object_will_be_initialized_successfully(self):
        parameters = {'source': '/test_dir_1/file.test'}

        parameters_object = ParametersContainer()
        parameters_processor.set_parameters_container(parameters_object)
        try:
            for parameter_name, parameter_value in parameters.items():
                parameters_processor.check_template_parameter(parameter_name,
                                                              parameter_value,
                                                              FILE, 1)
            parameters_processor.check_postparse_parameters()
        except Exception as error:
            pytest.fail('Unexpected exception: {0}'.
                        format(str(error)))

        assert parameters_object.source == join_paths(CHROOT_PATH,
                                                      '/test_dir_1/file.test')

    def test_if_TemplateParameters_object_is_intialized_as_dir_parameters_object_using_correct_source_parameter_with_append_link__the_object_will_be_initialized_successfully(self):
        parameters = {'append': 'link', 'source': '/test_dir_1'}

        parameters_object = ParametersContainer()
        parameters_processor.set_parameters_container(parameters_object)
        try:
            for parameter_name, parameter_value in parameters.items():
                parameters_processor.check_template_parameter(parameter_name,
                                                              parameter_value,
                                                              DIR, 1)

            parameters_processor.check_postparse_parameters()
        except Exception as error:
            pytest.fail('Unexpected exception: {0}'.
                        format(str(error)))

        assert parameters_object.source == join_paths(CHROOT_PATH,
                                                      '/test_dir_1')

    def test_if_TemplateParameters_object_is_intialized_using_source_parameter_with_unexisting_file_path__the_initialization_of_the_object_will_be_failed(self):
        parameters = {'source': '/test_dir_1/unexisted_file.test'}
        parameters_object = ParametersContainer()
        parameters_processor.set_parameters_container(parameters_object)

        with pytest.raises(IncorrectParameter):
            for parameter_name, parameter_value in parameters.items():
                parameters_processor.check_template_parameter(parameter_name,
                                                              parameter_value,
                                                              DIR, 1)
            parameters_processor.check_postparse_parameters()

    def test_if_TemplateParameters_object_is_intialized_as_dir_parameters_object_using_source_parameter_but_without_append_link__the_initialization_of_the_object_will_be_failed(self):
        parameters = {'source': '/test_dir_1/file.test'}
        parameters_object = ParametersContainer()
        parameters_processor.set_parameters_container(parameters_object)

        with pytest.raises(IncorrectParameter):
            for parameter_name, parameter_value in parameters.items():
                parameters_processor.check_template_parameter(parameter_name,
                                                              parameter_value,
                                                              DIR, 1)
            parameters_processor.check_postparse_parameters()

    def test_if_TemplateParameters_object_is_intialized_using_dictionary_with_correct_force_parameter__the_object_will_be_initialized_successfully(self):
        parameters = {'force': True}
        parameters_object = ParametersContainer()
        parameters_processor.set_parameters_container(parameters_object)

        try:
            for parameter_name, parameter_value in parameters.items():
                parameters_processor.check_template_parameter(parameter_name,
                                                              parameter_value,
                                                              DIR, 1)
            parameters_processor.check_postparse_parameters()
        except Exception as error:
            pytest.fail('Unexpected exception: {0}'.
                        format(str(error)))

        assert parameters_object.force

    def test_if_TemplateParameters_object_is_intialized_using_dictionary_with_incorrect_force_parameter__the_initialization_of_the_object_will_be_failed(self):
        parameters = {'force': 'value'}
        parameters_object = ParametersContainer()
        parameters_processor.set_parameters_container(parameters_object)

        with pytest.raises(IncorrectParameter):
            for parameter_name, parameter_value in parameters.items():
                parameters_processor.check_template_parameter(parameter_name,
                                                              parameter_value,
                                                              FILE, 1)
            parameters_processor.check_postparse_parameters()

    def test_if_TemplateParameters_object_is_intialized_using_dictionary_with_autoupdate_parameter__a_value_of_the_parameter_will_be_checked(self):
        parameters = {'autoupdate': True}
        parameters_object = ParametersContainer()
        parameters_processor.set_parameters_container(parameters_object)

        try:
            for parameter_name, parameter_value in parameters.items():
                parameters_processor.check_template_parameter(parameter_name,
                                                              parameter_value,
                                                              FILE, 1)
            parameters_processor.check_postparse_parameters()
        except Exception as error:
            pytest.fail('Unexpected exception: {0}'.
                        format(str(error)))

        assert parameters_object.autoupdate

    def test_if_TemplateParameters_object_is_intialized_using_dictionary_with_incorrect_autoupdate_parameter__the_initialization_of_the_object_will_be_failed(self):
        parameters = {'autoupdate': 'value'}
        parameters_object = ParametersContainer()
        parameters_processor.set_parameters_container(parameters_object)

        with pytest.raises(IncorrectParameter):
            for parameter_name, parameter_value in parameters.items():
                parameters_processor.check_template_parameter(parameter_name,
                                                              parameter_value,
                                                              FILE, 1)
            parameters_processor.check_postparse_parameters()

    def test_if_TemplateParameters_object_is_intialized_using_dictionary_with_correct_chown_parameter__the_object_will_be_initialized_successfully(self):
        parameters = {'chown': 'root:root'}
        parameters_object = ParametersContainer()
        parameters_processor.set_parameters_container(parameters_object)

        try:
            for parameter_name, parameter_value in parameters.items():
                parameters_processor.check_template_parameter(parameter_name,
                                                              parameter_value,
                                                              FILE, 1)
            parameters_processor.check_postparse_parameters()
        except Exception as error:
            pytest.fail('Unexpected exception: {0}'.
                        format(str(error)))

        assert parameters_object.chown == {'uid': 0, 'gid': 0}

    def test_if_TemplateParameters_object_is_initialized_using_dictionary_with_correct_chown_parameter_and_new_chroot_path__the_object_will_be_initialized_successfully(self):
        parameters = {'chown': 'divanov:guest'}
        parameters_object = ParametersContainer()
        parameters_processor.set_parameters_container(parameters_object)

        try:
            for parameter_name, parameter_value in parameters.items():
                parameters_processor.check_template_parameter(parameter_name,
                                                              parameter_value,
                                                              FILE, 1)
            parameters_processor.check_postparse_parameters()
        except Exception as error:
            pytest.fail('Unexpected exception: {0}'.
                        format(str(error)))

        assert parameters_object.chown == {'uid': 666, 'gid': 1000}

    def test_if_TemplateParameters_object_is_intialized_using_dictionary_with_correct_chown_parameter_in_its_digital_form__the_object_will_be_initialized_successfully(self):
        uid = os.getuid()
        gid = os.getgid()
        parameters = {'chown': '{0}:{1}'.format(uid, gid)}
        parameters_object = ParametersContainer()
        parameters_processor.set_parameters_container(parameters_object)

        try:
            for parameter_name, parameter_value in parameters.items():
                parameters_processor.check_template_parameter(parameter_name,
                                                              parameter_value,
                                                              FILE, 1)
            parameters_processor.check_postparse_parameters()
        except Exception as error:
            pytest.fail('Unexpected exception: {0}'.
                        format(str(error)))

        assert parameters_object.chown == {'uid': uid, 'gid': gid}

    def test_if_TemplateParameters_object_is_intialized_using_dictionary_with_incorrect_chown_parameter__the_initialization_of_the_object_will_be_failed(self):
        parameters = {'chown': 'wrong_user_name:wrong_group_name'}
        parameters_object = ParametersContainer()
        parameters_processor.set_parameters_container(parameters_object)

        with pytest.raises(IncorrectParameter):
            for parameter_name, parameter_value in parameters.items():
                parameters_processor.check_template_parameter(parameter_name,
                                                              parameter_value,
                                                              FILE, 1)
            parameters_processor.check_postparse_parameters()

    def test_if_TemplateParameters_object_is_intialized_using_dictionary_with_correct_chmod_parameter__the_object_will_be_initialized_successfully(self):
        parameters = {'chmod': 'rw-r--r--'}
        parameters_object = ParametersContainer()
        parameters_processor.set_parameters_container(parameters_object)

        try:
            for parameter_name, parameter_value in parameters.items():
                parameters_processor.check_template_parameter(parameter_name,
                                                              parameter_value,
                                                              FILE, 1)
            parameters_processor.check_postparse_parameters()
        except Exception as error:
            pytest.fail('Unexpected exception: {0}'.
                        format(str(error)))

        assert parameters_object.chmod == 0o644

    def test_if_TemplateParameters_object_is_intialized_using_dictionary_with_correct_chmod_parameter_in_its_digital_form__the_object_will_be_initialized_successfully(self):
        parameters = {'chmod': '600'}
        parameters_object = ParametersContainer()
        parameters_processor.set_parameters_container(parameters_object)

        try:
            for parameter_name, parameter_value in parameters.items():
                parameters_processor.check_template_parameter(parameter_name,
                                                              parameter_value,
                                                              FILE, 1)
            parameters_processor.check_postparse_parameters()
        except Exception as error:
            pytest.fail('Unexpected exception: {0}'.
                        format(str(error)))

        assert parameters_object.chmod == 0o600
