# Copyright © 2019,2021 Intel Corporation

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

import sys
import textwrap
import typing

import pytest

# AsyncMock is new in 3.8, so if we're using an older version we need the
# backported version of mock
if sys.version_info >= (3, 8):
    from unittest import mock
else:
    import mock

from .gen_release_notes import *


@pytest.mark.parametrize(
    'current, is_point, expected',
    [
        ('19.2.0', True, '19.2.1'),
        ('19.3.6', True, '19.3.7'),
        ('20.0.0-rc4', False, '20.0.0'),
    ])
def test_next_version(current: str, is_point: bool, expected: str) -> None:
    assert calculate_next_version(current, is_point) == expected


@pytest.mark.parametrize(
    'current, is_point, expected',
    [
        ('19.3.6', True, '19.3.6'),
        ('20.0.0-rc4', False, '19.3.0'),
    ])
def test_previous_version(current: str, is_point: bool, expected: str) -> None:
    assert calculate_previous_version(current, is_point) == expected


@pytest.mark.asyncio
async def test_get_shortlog():
    # Certainly not perfect, but it's something
    version = '19.2.0'
    out = await get_shortlog(version)
    assert out


@pytest.mark.asyncio
async def test_gather_commits():
    # Certainly not perfect, but it's something
    version = '19.2.0'
    out = await gather_commits(version)
    assert out


@pytest.mark.asyncio
@pytest.mark.parametrize(
    'content, bugs',
    [
        # It is important to have the title on a new line, as
        # textwrap.dedent wont work otherwise.

        # Test the `Closes: #N` syntax
        (
            '''\
            A commit

            It has a message in it

            Closes: #1
            ''',
            ['1'],
        ),

        # Test the Full url
        (
            '''\
            A commit with no body

            Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3456
            ''',
            ['3456'],
        ),

        # Test projects that are not mesa
        (
            '''\
            A commit for libdrm

            Closes: https://gitlab.freedesktop.org/mesa/drm/-/3456
            ''',
            [],
        ),
        (
            '''\
            A commit for for something else completely

            Closes: https://github.com/Organiztion/project/1234
            ''',
            [],
        ),

        # Test  multiple issues on one line
        (
            '''\
            Fix many bugs

            Closes: #1, #2
            ''',
            ['1', '2'],
        ),

        # Test multiple closes
        (
            '''\
            Fix many bugs

            Closes: #1
            Closes: #2
            ''',
            ['1', '2'],
        ),
        (
            '''\
            With long form

            Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3456
            Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3457
            Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3458
            ''',
            ['3456', '3457', '3458'],
        ),
    ])
async def test_parse_issues(content: str, bugs: typing.List[str]) -> None:
    mock_com = mock.AsyncMock(return_value=(textwrap.dedent(content).encode(), ''))
    mock_p = mock.Mock()
    mock_p.communicate = mock_com
    mock_exec = mock.AsyncMock(return_value=mock_p)

    with mock.patch('bin.gen_release_notes.asyncio.create_subprocess_exec', mock_exec), \
            mock.patch('bin.gen_release_notes.gather_commits', mock.AsyncMock(return_value='sha\n')):
        ids = await parse_issues('1234 not used')
        assert set(ids) == set(bugs)
