# Copyright (C) 2015-2021 ycmd contributors
#
# This file is part of ycmd.
#
# ycmd is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# ycmd is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with ycmd.  If not, see <http://www.gnu.org/licenses/>.

from hamcrest import ( assert_that,
                       contains_inanyorder,
                       equal_to,
                       has_entries )
import pprint
import requests
from unittest import TestCase
from ycmd.tests.test_utils import CombineRequest
from ycmd.tests.javascriptreact import setUpModule, tearDownModule # noqa
from ycmd.tests.javascriptreact import PathToTestFile, SharedYcmd
from ycmd.utils import ReadFile


def RunTest( app, test ):
  contents = ReadFile( test[ 'request' ][ 'filepath' ] )

  app.post_json(
    '/event_notification',
    CombineRequest( test[ 'request' ], {
      'contents': contents,
      'filetype': 'javascriptreact',
      'event_name': 'BufferVisit'
    } )
  )

  app.post_json(
    '/event_notification',
    CombineRequest( test[ 'request' ], {
      'contents': contents,
      'filetype': 'javascriptreact',
      'event_name': 'FileReadyToParse'
    } )
  )

  # We ignore errors here and check the response code ourself.
  # This is to allow testing of requests returning errors.
  response = app.post_json(
    '/run_completer_command',
    CombineRequest( test[ 'request' ], {
      'contents': contents,
      'filetype': 'javascriptreact',
      'command_arguments': ( [ test[ 'request' ][ 'command' ] ]
                             + test[ 'request' ].get( 'arguments', [] ) )
    } ),
    expect_errors = True
  )

  print( f'completer response: { pprint.pformat( response.json ) }' )

  assert_that( response.status_code,
               equal_to( test[ 'expect' ][ 'response' ] ) )

  assert_that( response.json, test[ 'expect' ][ 'data' ] )


class SubcommandsTest( TestCase ):
  @SharedYcmd
  def test_Subcommands_GoToReferences( self, app ):
    RunTest( app, {
      'description': 'GoToReferences works',
      'request': {
        'command': 'GoToReferences',
        'line_num': 6,
        'column_num': 4,
        'filepath': PathToTestFile( 'test.jsx' ),
      },
      'expect': {
        'response': requests.codes.ok,
        'data': contains_inanyorder(
          has_entries( { 'description': 'function HelloMessage({ name }) {',
                         'line_num'   : 1,
                         'column_num' : 10,
                         'filepath'   : PathToTestFile( 'test.jsx' ) } ),
          has_entries( { 'description': '  <HelloMessage name="Taylor" />,',
                         'line_num'   : 6,
                         'column_num' : 4,
                         'filepath'   : PathToTestFile( 'test.jsx' ) } ),
        )
      }
    } )
