from app.data_model.answer_store import AnswerStore
from app.questionnaire.location import Location
from app.questionnaire.questionnaire_schema import QuestionnaireSchema
from app.submitter.convert_payload_0_0_1 import convert_answers_to_payload_0_0_1
from app.submitter.converter import convert_answers
from tests.app.submitter.schema import make_schema
from tests.app.submitter.test_converter import TestConverter, create_answer


class TestConvertPayload001(TestConverter):  # pylint: disable=too-many-public-methods

    def test_convert_answers_to_payload_0_0_1_with_key_error(self):
        with self._app.test_request_context():
            user_answer = [create_answer('ABC', '2016-01-01', group_id='group-1', block_id='block-1'),
                           create_answer('DEF', '2016-03-30', group_id='group-1', block_id='block-1'),
                           create_answer('GHI', '2016-05-30', group_id='group-1', block_id='block-1')]

            questionnaire = make_schema('0.0.1', 'section-1', 'group-1', 'block-1', [
                {
                    'id': 'question-1',
                    'answers': [
                        {
                            'id': 'LMN',
                            'type': 'TextField',
                            'q_code': '001'
                        },
                        {
                            'id': 'DEF',
                            'type': 'TextField',
                            'q_code': '002'
                        },
                        {
                            'id': 'JKL',
                            'type': 'TextField',
                            'q_code': '003'
                        }
                    ]
                }
            ])

            routing_path = [Location(group_id='group-1', group_instance=0, block_id='block-1')]
            answer_object = (convert_answers_to_payload_0_0_1(AnswerStore(user_answer), QuestionnaireSchema(questionnaire), routing_path))
            self.assertEqual(answer_object['002'], '2016-03-30')
            self.assertEqual(len(answer_object), 1)

    def test_answer_with_zero(self):
        with self._app.test_request_context():
            user_answer = [create_answer('GHI', 0, group_id='group-1', block_id='block-1')]

            questionnaire = make_schema('0.0.1', 'section-1', 'group-1', 'block-1', [
                {
                    'id': 'question-2',
                    'answers': [
                        {
                            'id': 'GHI',
                            'type': 'TextField',
                            'q_code': '003'
                        }
                    ]
                }
            ])

            routing_path = [Location(group_id='group-1', group_instance=0, block_id='block-1')]

            answer_object = convert_answers(self.metadata, self.collection_metadata, QuestionnaireSchema(questionnaire), AnswerStore(user_answer), routing_path)

            # Check the converter correctly
            self.assertEqual('0', answer_object['data']['003'])

    def test_answer_with_float(self):
        with self._app.test_request_context():
            user_answer = [create_answer('GHI', 10.02, group_id='group-1', block_id='block-1')]

            questionnaire = make_schema('0.0.1', 'section-1', 'group-1', 'block-1', [
                {
                    'id': 'question-2',
                    'answers': [
                        {
                            'id': 'GHI',
                            'type': 'TextField',
                            'q_code': '003'
                        }
                    ]
                }
            ])

            routing_path = [Location(group_id='group-1', group_instance=0, block_id='block-1')]

            answer_object = convert_answers(self.metadata, self.collection_metadata, QuestionnaireSchema(questionnaire), AnswerStore(user_answer), routing_path)

            # Check the converter correctly
            self.assertEqual('10.02', answer_object['data']['003'])

    def test_answer_with_string(self):
        with self._app.test_request_context():
            user_answer = [create_answer('GHI', 'String test + !', group_id='group-1', block_id='block-1')]

            questionnaire = make_schema('0.0.1', 'section-1', 'group-1', 'block-1', [
                {
                    'id': 'question-2',
                    'answers': [
                        {
                            'id': 'GHI',
                            'type': 'TextField',
                            'q_code': '003'
                        }
                    ]
                }
            ])

            routing_path = [Location(group_id='group-1', group_instance=0, block_id='block-1')]

            answer_object = convert_answers(self.metadata, self.collection_metadata, QuestionnaireSchema(questionnaire), AnswerStore(user_answer), routing_path)

            # Check the converter correctly
            self.assertEqual('String test + !', answer_object['data']['003'])

    def test_answer_with_multiple_instances(self):
        with self._app.test_request_context():
            user_answer = [create_answer('GHI', 0, group_id='group-1', block_id='block-1'),
                           create_answer('GHI', value=1, answer_instance=1, group_id='group-1', block_id='block-1'),
                           create_answer('GHI', value=2, answer_instance=2, group_id='group-1', block_id='block-1')]

            questionnaire = make_schema('0.0.1', 'section-1', 'group-1', 'block-1', [
                {
                    'id': 'question-2',
                    'answers': [
                        {
                            'id': 'GHI',
                            'type': 'TextField',
                            'q_code': '003'
                        }
                    ]
                }
            ])

            routing_path = [Location(group_id='group-1', group_instance=0, block_id='block-1')]

            answer_object = convert_answers(self.metadata, self.collection_metadata, QuestionnaireSchema(questionnaire), AnswerStore(user_answer), routing_path)

            # Check the converter correctly
            self.assertEqual(answer_object['data']['003'], ['0', '1', '2'])

    def test_answer_without_qcode(self):
        with self._app.test_request_context():
            user_answer = [create_answer('GHI', 'String test + !', group_id='group-1', block_id='block-1')]

            questionnaire = make_schema('0.0.1', 'section-1', 'group-1', 'block-1', [
                {
                    'id': 'question-2',
                    'answers': [
                        {
                            'id': 'GHI',
                            'type': 'TextField'
                        }
                    ]
                }
            ])

            routing_path = [Location(group_id='group-1', group_instance=0, block_id='block-1')]

            answer_object = convert_answers(self.metadata, self.collection_metadata, QuestionnaireSchema(questionnaire), AnswerStore(user_answer), routing_path)

            self.assertEqual(len(answer_object['data']), 0)

    def test_get_checkbox_answer_with_duplicate_detail_answer_ids(self):
        with self._app.test_request_context():
            routing_path = [Location(group_id='favourite-food', group_instance=0, block_id='crisps')]
            answers = [create_answer('crisps-answer', [
                'Ready salted',
                'Other'
            ], group_id='favourite-food', block_id='crisps')]

            answers += [create_answer('other-answer-mandatory', 'Other', group_id='favourite-food', block_id='crisps',
                                      group_instance=1)]
            answers += [create_answer('other-answer-mandatory', 'Other', group_id='favourite-food', block_id='crisps',
                                      group_instance=1)]

            questionnaire = make_schema('0.0.1', 'section-1', 'favourite-food', 'crisps', [
                {
                    'id': 'crisps-question',
                    'answers': [
                        {
                            'id': 'crisps-answer',
                            'type': 'Checkbox',
                            'options': [
                                {
                                    'label': 'Other',
                                    'q_code': '4',
                                    'description': 'Choose any other flavour',
                                    'value': 'Other',
                                    'detail_answer': {'id': 'other-answer-mandatory'}
                                }
                            ]
                        }
                    ]
                }
            ])

        with self.assertRaises(Exception) as err:
            convert_answers(self.metadata, self.collection_metadata, QuestionnaireSchema(questionnaire), AnswerStore(answers), routing_path)
        self.assertEqual('Multiple answers found for {}'.format('other-answer-mandatory'), str(err.exception))

    def test_converter_checkboxes_with_q_codes(self):
        with self._app.test_request_context():
            routing_path = [Location(group_id='favourite-food', group_instance=0, block_id='crisps')]
            answers = [create_answer('crisps-answer', [
                'Ready salted',
                'Sweet chilli'
            ], group_id='favourite-food', block_id='crisps')]

            questionnaire = make_schema('0.0.1', 'section-1', 'favourite-food', 'crisps', [
                {
                    'id': 'crisps-question',
                    'answers': [
                        {
                            'id': 'crisps-answer',
                            'type': 'Checkbox',
                            'options': [
                                {
                                    'label': 'Ready salted',
                                    'value': 'Ready salted',
                                    'q_code': '1'
                                },
                                {
                                    'label': 'Sweet chilli',
                                    'value': 'Sweet chilli',
                                    'q_code': '2'
                                },
                                {
                                    'label': 'Cheese and onion',
                                    'value': 'Cheese and onion',
                                    'q_code': '3'
                                },
                                {
                                    'label': 'Other',
                                    'q_code': '4',
                                    'description': 'Choose any other flavour',
                                    'value': 'Other',
                                    'detail_answer': {
                                        'mandatory': True,
                                        'id': 'other-answer-mandatory',
                                        'label': 'Please specify other',
                                        'type': 'TextField'
                                    }
                                }
                            ]
                        }
                    ]
                }
            ])

            # When
            answer_object = convert_answers(self.metadata, self.collection_metadata, QuestionnaireSchema(questionnaire), AnswerStore(answers), routing_path)

            # Then
            self.assertEqual(len(answer_object['data']), 2)
            self.assertEqual(answer_object['data']['1'], 'Ready salted')
            self.assertEqual(answer_object['data']['2'], 'Sweet chilli')

    def test_converter_checkboxes_with_q_codes_and_other_value(self):
        with self._app.test_request_context():
            routing_path = [Location(group_id='favourite-food', group_instance=0, block_id='crisps')]
            answers = [create_answer('crisps-answer', [
                'Ready salted',
                'Other'
            ], group_id='favourite-food', block_id='crisps')]

            answers += [create_answer('other-answer-mandatory', 'Bacon', group_id='favourite-food', block_id='crisps')]

            questionnaire = make_schema('0.0.1', 'section-1', 'favourite-food', 'crisps', [
                {
                    'id': 'crisps-question',
                    'answers': [
                        {
                            'id': 'crisps-answer',
                            'type': 'Checkbox',
                            'options': [
                                {
                                    'label': 'Ready salted',
                                    'value': 'Ready salted',
                                    'q_code': '1'
                                },
                                {
                                    'label': 'Sweet chilli',
                                    'value': 'Sweet chilli',
                                    'q_code': '2'
                                },
                                {
                                    'label': 'Cheese and onion',
                                    'value': 'Cheese and onion',
                                    'q_code': '3'
                                },
                                {
                                    'label': 'Other',
                                    'q_code': '4',
                                    'description': 'Choose any other flavour',
                                    'value': 'Other',
                                    'detail_answer':  {
                                        'mandatory': True,
                                        'id': 'other-answer-mandatory',
                                        'label': 'Please specify other',
                                        'type': 'TextField'
                                    }
                                }
                            ]
                        }
                    ]
                }
            ])

            # When
            answer_object = convert_answers(self.metadata, self.collection_metadata, QuestionnaireSchema(questionnaire), AnswerStore(answers), routing_path)

            # Then
            self.assertEqual(len(answer_object['data']), 2)
            self.assertEqual(answer_object['data']['1'], 'Ready salted')
            self.assertEqual(answer_object['data']['4'], 'Bacon')

    def test_converter_checkboxes_with_q_codes_and_empty_other_value(self):
        with self._app.test_request_context():
            routing_path = [Location(group_id='favourite-food', group_instance=0, block_id='crisps')]
            answers = [create_answer('crisps-answer', [
                'Ready salted',
                'Other'
            ], group_id='favourite-food', block_id='crisps')]

            answers += [create_answer('other-answer-mandatory', '', group_id='favourite-food', block_id='crisps')]

            questionnaire = make_schema('0.0.1', 'section-1', 'favourite-food', 'crisps', [
                {
                    'id': 'crisps-question',
                    'answers': [
                        {
                            'id': 'crisps-answer',
                            'type': 'Checkbox',
                            'options': [
                                {
                                    'label': 'Ready salted',
                                    'value': 'Ready salted',
                                    'q_code': '1'
                                },
                                {
                                    'label': 'Sweet chilli',
                                    'value': 'Sweet chilli',
                                    'q_code': '2'
                                },