#
# Copyright (C) 2016 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#


"""A stub for the Sysroot class."""


import os

import error


class Error(error.Error):
    pass


class StubSysroot(object):
    """Replacement for Sysroots."""

    def __init__(self, path):
        self.path = path
        self.should_write = []
        self.last_written = ''
        self.written = []
        self.should_add_file = []
        self.should_add_dir = []
        self.should_add_glob = []
        self.should_pass_filter = []
        self.should_fail_filter = []
        self.should_makedirs = []

    def Path(self, *path):
        return os.path.join(self.path, *path)

    def WriteFile(self, path, contents):
        if path in self.should_write:
            self.last_written = contents
            self.written.append(contents)
            self.should_write.remove(path)
        else:
            raise IOError('not supposed to write {0}'.format(path))

    def AddFile(self, src, dest=''):
        if not (src, dest) in self.should_add_file:
            raise IOError('Not supposed to add file {0} to {1}'.format(src,
                                                                       dest))
        self.should_add_file.remove((src, dest))

    # pylint: disable=unused-argument
    def AddDir(self, src, dest=None, recurse=True, filter_func=None,
               symlinks=None):
        dest = dest or ''
        proper_filter = True
        if filter_func:
            proper_filter = (
                [f for f in self.should_pass_filter
                 if filter_func(f)] == self.should_pass_filter and
                [f for f in self.should_fail_filter if filter_func(f)] == [])

        if not proper_filter:
            raise Error('AddDir called with improper filter')
        if not (src, dest, recurse) in self.should_add_dir:
            raise IOError(('Not supposed to add dir "{}" to "{}", '
                           'recursive: {}').format(src, dest, recurse))

        self.should_add_dir.remove((src, dest, recurse))
        # This should walk path.should_exist if recurse.
        return [dest]

    # pylint: disable=unused-argument
    def AddGlob(self, src, dest=None, recurse=True, filter_func=None,
                symlinks=None):
        dest = dest or ''
        proper_filter = True
        if filter_func:
            proper_filter = (
                [f for f in self.should_pass_filter
                 if filter_func(f)] == self.should_pass_filter and
                [f for f in self.should_fail_filter if filter_func(f)] == [])

        if not proper_filter:
            raise Error('AddGlob called with improper filter')
        if not (src, dest, recurse) in self.should_add_glob:
            raise IOError(('Not supposed to add glob "{}" to "{}", '
                           'recursive: {}').format(src, dest, recurse))

        self.should_add_glob.remove((src, dest, recurse))
        # This should walk path.should_exist if recurse.
        return [dest]

    def Makedirs(self, dirs):
        if not dirs in self.should_makedirs:
            raise IOError('Could not make dirs {0}'.format(dirs))

    def Destroy(self):
        pass

class StubSysrootGenerator(object):
    """Generates stub sysroots."""

    def __init__(self):
        self.should_write = []
        self.last_written = ''
        self.should_add_file = []
        self.should_add_dir = []
        self.should_add_glob = []
        self.should_pass_filter = []
        self.should_fail_filter = []
        self.should_makedirs = []
        self.sysroots = []

    # pylint: disable=unused-argument
    def Sysroot(self, path, copy_newer_only=False):
        gen = StubSysroot(path)
        self.sysroots.append(gen)
        gen.should_write = self.should_write
        gen.last_written = self.last_written
        gen.should_add_file = self.should_add_file
        gen.should_add_dir = self.should_add_dir
        gen.should_add_glob = self.should_add_glob
        gen.should_pass_filter = self.should_pass_filter
        gen.should_fail_filter = self.should_fail_filter
        gen.should_makedirs = self.should_makedirs
        return gen
