# Copyright 2019 Red Hat, Inc.
# 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.

import typing as T


def parse(lines: T.Iterable[str]) -> T.List[T.Tuple[T.List[str], T.List[str]]]:
    rules: T.List[T.Tuple[T.List[str], T.List[str]]] = []
    targets: T.List[str] = []
    deps: T.List[str] = []
    in_deps = False
    out = ''
    for line in lines:
        if not line.endswith('\n'):
            line += '\n'
        escape = None
        for c in line:
            if escape:
                if escape == '$' and c != '$':
                    out += '$'
                if escape == '\\' and c == '\n':
                    continue
                out += c
                escape = None
                continue
            if c == '\\' or c == '$':
                escape = c
                continue
            elif c in (' ', '\n'):
                if out != '':
                    if in_deps:
                        deps.append(out)
                    else:
                        targets.append(out)
                out = ''
                if c == '\n':
                    rules.append((targets, deps))
                    targets = []
                    deps = []
                    in_deps = False
                continue
            elif c == ':':
                targets.append(out)
                out = ''
                in_deps = True
                continue
            out += c
    return rules

class Target(T.NamedTuple):

    deps: T.Set[str]


class DepFile:
    def __init__(self, lines: T.Iterable[str]):
        rules = parse(lines)
        depfile: T.Dict[str, Target] = {}
        for (targets, deps) in rules:
            for target in targets:
                t = depfile.setdefault(target, Target(deps=set()))
                for dep in deps:
                    t.deps.add(dep)
        self.depfile = depfile

    def get_all_dependencies(self, name: str, visited: T.Optional[T.Set[str]] = None) -> T.List[str]:
        deps: T.Set[str] = set()
        if not visited:
            visited = set()
        if name in visited:
            return []
        visited.add(name)

        target = self.depfile.get(name)
        if not target:
            return []
        deps.update(target.deps)
        for dep in target.deps:
            deps.update(self.get_all_dependencies(dep, visited))
        return sorted(deps)
