# Copyright (C) 2010-2024 RhodeCode GmbH
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# This program 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 Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/

import datetime

import pytest

from rhodecode.lib.str_utils import safe_bytes
from rhodecode.lib.vcs.nodes import FileNode
from rhodecode.lib.vcs_common import NodeKind
from rhodecode.tests.vcs.conftest import BackendTestMixin


class TestFileNodesListingAndCaches:
    def test_filenode_get_root_node(self, vcsbackend):
        repo = vcsbackend.repo
        commit = repo.get_commit()

        # check if we start with empty nodes cache
        assert commit.nodes == {}
        assert commit._path_mode_cache == {}
        assert commit._path_type_cache == {}

        top_dir = commit.get_node(b"")

        assert top_dir.is_dir()

        assert list(commit.nodes.keys()) == [b""]
        assert list(commit._path_type_cache.keys()) == [b""]
        assert commit._path_mode_cache == {}

    def test_filenode_get_file_node(self, vcsbackend):
        repo = vcsbackend.repo
        commit = repo.get_commit()

        # check if we start with empty nodes cache
        assert commit.nodes == {}
        assert commit._path_mode_cache == {}
        assert commit._path_type_cache == {}

        file_node = commit.get_node(b"README.rst")

        assert file_node.is_file()
        assert file_node.last_commit

        assert list(commit.nodes.keys()) == [b"README.rst"]
        if repo.alias == "hg":
            assert commit._path_type_cache == {b"README.rst": NodeKind.FILE}
            assert commit._path_mode_cache == {b"README.rst": 33188}

        if repo.alias == "git":
            assert commit._path_type_cache == {
                b"README.rst": ["8f111ab5152b9fd34f52b0fb288e1216b5d2f55e", NodeKind.FILE]
            }
            assert commit._path_mode_cache == {b"README.rst": 33188}

        if repo.alias == "svn":
            assert commit._path_type_cache == {b"README.rst": NodeKind.FILE}
            assert commit._path_mode_cache == {b"README.rst": 33188}

    def test_filenode_get_nodes_from_top_dir(self, vcsbackend):
        repo = vcsbackend.repo
        commit = repo.get_commit()

        # check if we start with empty nodes cache
        assert commit.nodes == {}
        assert commit._path_mode_cache == {}
        assert commit._path_type_cache == {}

        node_list = commit.get_nodes(b"")

        for node in node_list:
            assert node

        if repo.alias == "svn":
            assert list(commit.nodes.keys()) == [
                b"README",
                b".hgignore",
                b"MANIFEST.in",
                b".travis.yml",
                b"vcs",
                b"tox.ini",
                b"setup.py",
                b"setup.cfg",
                b"docs",
                b"fakefile",
                b"examples",
                b"test_and_report.sh",
                b"bin",
                b".gitignore",
                b".hgtags",
                b"README.rst",
            ]
            assert commit._path_type_cache == {
                b"": NodeKind.DIR,
                b"README": 2,
                b".hgignore": 2,
                b"MANIFEST.in": 2,
                b".travis.yml": 2,
                b"vcs": 1,
                b"tox.ini": 2,
                b"setup.py": 2,
                b"setup.cfg": 2,
                b"docs": 1,
                b"fakefile": 2,
                b"examples": 1,
                b"test_and_report.sh": 2,
                b"bin": 1,
                b".gitignore": 2,
                b".hgtags": 2,
                b"README.rst": 2,
            }
            assert commit._path_mode_cache == {}

        if repo.alias == "hg":
            assert list(commit.nodes.keys()) == [
                b".gitignore",
                b".hgignore",
                b".hgtags",
                b".travis.yml",
                b"MANIFEST.in",
                b"README",
                b"README.rst",
                b"docs",
                b"run_test_and_report.sh",
                b"setup.cfg",
                b"setup.py",
                b"test_and_report.sh",
                b"tox.ini",
                b"vcs",
            ]

            assert commit._path_type_cache == {
                b"": NodeKind.DIR,
                b".gitignore": 2,
                b".hgignore": 2,
                b".hgtags": 2,
                b".travis.yml": 2,
                b"MANIFEST.in": 2,
                b"README": 2,
                b"README.rst": 2,
                b"docs": 1,
                b"run_test_and_report.sh": 2,
                b"setup.cfg": 2,
                b"setup.py": 2,
                b"test_and_report.sh": 2,
                b"tox.ini": 2,
                b"vcs": 1,
            }
            assert commit._path_mode_cache == {
                b".gitignore": 33188,
                b".hgignore": 33188,
                b".hgtags": 33188,
                b".travis.yml": 33188,
                b"MANIFEST.in": 33188,
                b"README": 40960,
                b"README.rst": 33188,
                b"docs": 33188,
                b"run_test_and_report.sh": 33261,
                b"setup.cfg": 33188,
                b"setup.py": 33188,
                b"test_and_report.sh": 33261,
                b"tox.ini": 33188,
                b"vcs": 33188,
            }

        if repo.alias == "git":
            assert list(commit.nodes.keys()) == [
                b".gitignore",
                b".hgignore",
                b".hgtags",
                b"MANIFEST.in",
                b"README",
                b"README.rst",
                b"docs",
                b"run_test_and_report.sh",
                b"setup.cfg",
                b"setup.py",
                b"test_and_report.sh",
                b"tox.ini",
                b"vcs",
            ]
            assert commit._path_type_cache == {
                b"": ["2dab7f7377e36948b5633ae0877310380fdf64ba", NodeKind.DIR],
                b".gitignore": ["7f95b0917e31b0cce1ad96a033b1a814c420cde3", 2],
                b".hgignore": ["9bdee5ed67ceed7c4b5589ba26dada65df151aed", 2],
                b".hgtags": ["63aa2e892deebdfdef1845fe52e2418ade03557b", 2],
                b"MANIFEST.in": ["6d65aca5321c26589ae197b81511445cfb353c95", 2],
                b"README": ["92cacd285355271487b7e379dba6ca60f9a554a4", 2],
                b"README.rst": ["8f111ab5152b9fd34f52b0fb288e1216b5d2f55e", 2],
                b"docs": ["eaa8cef76ec4e1baf06f515ab03bfc01719a913d", 1],
                b"run_test_and_report.sh": ["e17011bdddc8812fda96e891a1087c73054f1f25", 2],
                b"setup.cfg": ["2e76b65bc9106ed466d71fb2cfe710352eadfb49", 2],
                b"setup.py": ["ccda2bd076eca961059deba6e39fb591d014052a", 2],
                b"test_and_report.sh": ["0b14056dd7dc759a9719adef3d7bb529141a740e", 2],
                b"tox.ini": ["c1735231e7af32f089b95455162db092824715a4", 2],
                b"vcs": ["5868c69a8d74ccf3fdc655af8f3f185bc0ff2ef6", 1],
            }
            assert commit._path_mode_cache == {
                b".gitignore": 33188,
                b".hgignore": 33188,
                b".hgtags": 33188,
                b"MANIFEST.in": 33188,
                b"README": 40960,
                b"README.rst": 33188,
                b"docs": 16384,
                b"run_test_and_report.sh": 33261,
                b"setup.cfg": 33188,
                b"setup.py": 33188,
                b"test_and_report.sh": 33261,
                b"tox.ini": 33188,
                b"vcs": 16384,
            }

    def test_filenode_get_nodes_from_docs_dir(self, vcsbackend):
        repo = vcsbackend.repo
        commit = repo.get_commit()

        # check if we start with empty nodes cache
        assert commit.nodes == {}
        assert commit._path_mode_cache == {}
        assert commit._path_type_cache == {}

        node_list = commit.get_nodes(b"docs")

        for node in node_list:
            assert node
