class EventNotification_test(object):
    def setUp(self):
        options = dict(user_options_store.DefaultOptions())
        options.update(DEFAULT_CLIENT_OPTIONS)
        user_options_store.SetAll(options)

        self.server_state = YouCompleteMe(user_options_store.GetAll())
        pass

    def tearDown(self):
        if self.server_state:
            self.server_state.OnVimLeave()

    @patch('vim.command')
    def FileReadyToParse_NonDiagnostic_Error_test(self, vim_command):
        # This test validates the behaviour of YouCompleteMe.ValidateParseRequest in
        # combination with YouCompleteMe.OnFileReadyToParse when the completer
        # raises an exception handling FileReadyToParse event notification
        ERROR_TEXT = 'Some completer response text'

        def ErrorResponse(*args):
            raise RuntimeError(ERROR_TEXT)

        with MockArbitraryBuffer('javascript'):
            with MockEventNotification(ErrorResponse):
                self.server_state.OnFileReadyToParse()
                assert self.server_state.DiagnosticsForCurrentFileReady()
                self.server_state.ValidateParseRequest()

                # The first call raises a warning
                vim_command.assert_has_calls([
                    PostVimMessage_Call(ERROR_TEXT),
                ])

                # Subsequent calls don't re-raise the warning
                self.server_state.ValidateParseRequest()
                vim_command.assert_has_calls([
                    PostVimMessage_Call(ERROR_TEXT),
                ])

                # But it does if a subsequent event raises again
                self.server_state.OnFileReadyToParse()
                assert self.server_state.DiagnosticsForCurrentFileReady()
                self.server_state.ValidateParseRequest()
                vim_command.assert_has_calls([
                    PostVimMessage_Call(ERROR_TEXT),
                    PostVimMessage_Call(ERROR_TEXT),
                ])

    @patch('vim.command')
    def FileReadyToParse_NonDiagnostic_Error_NonNative_test(self, vim_command):
        with MockArbitraryBuffer('javascript'):
            with MockEventNotification(None, False):
                self.server_state.OnFileReadyToParse()
                self.server_state.ValidateParseRequest()
                vim_command.assert_not_called()

    @patch('ycm.client.event_notification._LoadExtraConfFile')
    @patch('ycm.client.event_notification._IgnoreExtraConfFile')
    def FileReadyToParse_NonDiagnostic_ConfirmExtraConf_test(
            self, ignore_extra_conf, load_extra_conf, *args):

        # This test validates the behaviour of YouCompleteMe.ValidateParseRequest in
        # combination with YouCompleteMe.OnFileReadyToParse when the completer
        # raises the (special) UnknownExtraConf exception

        FILE_NAME = 'a_file'
        MESSAGE = ('Found ' + FILE_NAME + '. Load? \n\n(Question can be '
                   'turned off with options, see YCM docs)')

        def UnknownExtraConfResponse(*args):
            raise UnknownExtraConf(FILE_NAME)

        with MockArbitraryBuffer('javascript'):
            with MockEventNotification(UnknownExtraConfResponse):

                # When the user accepts the extra conf, we load it
                with patch('ycm.vimsupport.PresentDialog',
                           return_value=0) as present_dialog:
                    self.server_state.OnFileReadyToParse()
                    assert self.server_state.DiagnosticsForCurrentFileReady()
                    self.server_state.ValidateParseRequest()

                    present_dialog.assert_has_calls([
                        PresentDialog_Confirm_Call(MESSAGE),
                    ])
                    load_extra_conf.assert_has_calls([
                        call(FILE_NAME),
                    ])

                    # Subsequent calls don't re-raise the warning
                    self.server_state.ValidateParseRequest()

                    present_dialog.assert_has_calls(
                        [PresentDialog_Confirm_Call(MESSAGE)])
                    load_extra_conf.assert_has_calls([
                        call(FILE_NAME),
                    ])

                    # But it does if a subsequent event raises again
                    self.server_state.OnFileReadyToParse()
                    assert self.server_state.DiagnosticsForCurrentFileReady()
                    self.server_state.ValidateParseRequest()

                    present_dialog.assert_has_calls([
                        PresentDialog_Confirm_Call(MESSAGE),
                        PresentDialog_Confirm_Call(MESSAGE),
                    ])
                    load_extra_conf.assert_has_calls([
                        call(FILE_NAME),
                        call(FILE_NAME),
                    ])

                # When the user rejects the extra conf, we reject it
                with patch('ycm.vimsupport.PresentDialog',
                           return_value=1) as present_dialog:
                    self.server_state.OnFileReadyToParse()
                    assert self.server_state.DiagnosticsForCurrentFileReady()
                    self.server_state.ValidateParseRequest()

                    present_dialog.assert_has_calls([
                        PresentDialog_Confirm_Call(MESSAGE),
                    ])
                    ignore_extra_conf.assert_has_calls([
                        call(FILE_NAME),
                    ])

                    # Subsequent calls don't re-raise the warning
                    self.server_state.ValidateParseRequest()

                    present_dialog.assert_has_calls(
                        [PresentDialog_Confirm_Call(MESSAGE)])
                    ignore_extra_conf.assert_has_calls([
                        call(FILE_NAME),
                    ])

                    # But it does if a subsequent event raises again
                    self.server_state.OnFileReadyToParse()
                    assert self.server_state.DiagnosticsForCurrentFileReady()
                    self.server_state.ValidateParseRequest()

                    present_dialog.assert_has_calls([
                        PresentDialog_Confirm_Call(MESSAGE),
                        PresentDialog_Confirm_Call(MESSAGE),
                    ])
                    ignore_extra_conf.assert_has_calls([
                        call(FILE_NAME),
                        call(FILE_NAME),
                    ])