# Copyright (C) 2015 Mozilla Contributors
#
# This program 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 2
# of the License, or (at your option) any later version.
#
# 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 General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#
# As a special exception, the copyright holders of this code give you
# permission to combine this code with the software known as 'mozbuild',
# and to distribute those combinations without any restriction
# coming from the use of this file. (The General Public License
# restrictions do apply in other respects; for example, they cover
# modification of the file, and distribution when not combined with
# mozbuild.)
#
# If you modify this code, you may extend this exception to your
# version of the code, but you are not obliged to do so. If you
# do not wish to do so, delete this exception statement from your
# version.

from __future__ import absolute_import

import mercurial.error as error
import mercurial.hg as hg
import mercurial.ui as hgui

from .files import (
    BaseFinder,
    MercurialFile,
)
import mozpack.path as mozpath


# This isn't a complete implementation of BaseFile. But it is complete
# enough for moz.build reading.
class MercurialNativeFile(MercurialFile):
    def __init__(self, data):
        self.data = data

    def read(self):
        return self.data


class MercurialNativeRevisionFinder(BaseFinder):
    def __init__(self, repo, rev='.', recognize_repo_paths=False):
        """Create a finder attached to a specific changeset.

        Accepts a Mercurial localrepo and changectx instance.
        """
        if isinstance(repo, (str, unicode)):
            path = repo
            repo = hg.repository(hgui.ui(), repo)
        else:
            path = repo.root

        super(MercurialNativeRevisionFinder, self).__init__(base=repo.root)

        self._repo = repo
        self._rev = rev
        self._root = mozpath.normpath(path)
        self._recognize_repo_paths = recognize_repo_paths

    def _find(self, pattern):
        if self._recognize_repo_paths:
            raise NotImplementedError('cannot use find with recognize_repo_path')

        return self._find_helper(pattern, self._repo[self._rev], self._get)

    def get(self, path):
        if self._recognize_repo_paths:
            if not path.startswith(self._root):
                raise ValueError('lookups in recognize_repo_paths mode must be '
                                 'prefixed with repo path: %s' % path)
            path = path[len(self._root) + 1:]

        return self._get(path)

    def _get(self, path):
        if isinstance(path, unicode):
            path = path.encode('utf-8', 'replace')

        try:
            fctx = self._repo.filectx(path, self._rev)
            return MercurialNativeFile(fctx.data())
        except error.LookupError:
            return None