# Portions copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
# pyre-unsafe
"""Parser for future statements

"""
from __future__ import print_function

import ast

from .visitor import ASTVisitor, walk


def is_future(stmt):
    """Return true if statement is a well-formed future statement"""
    if not isinstance(stmt, ast.ImportFrom):
        return 0
    if stmt.module == "__future__":
        return 1
    else:
        return 0


class FutureParser(ASTVisitor):

    features = (
        "nested_scopes",
        "generators",
        "division",
        "absolute_import",
        "with_statement",
        "print_function",
        "unicode_literals",
        "generator_stop",
        "barry_as_FLUFL",
        "annotations",
    )

    def __init__(self):
        super().__init__()
        self.found = {}  # set

    def visitModule(self, node):
        for s in node.body:
            if isinstance(s, ast.Expr) and isinstance(s.value, ast.Str):
                continue
            if not self.check_stmt(s):
                break

    def check_stmt(self, stmt):
        if is_future(stmt):
            for alias in stmt.names:
                name = alias.name
                if name in self.features:
                    self.found[name] = 1
                elif name == "braces":
                    raise SyntaxError("not a chance")
                else:
                    raise SyntaxError("future feature %s is not defined" % name)
            stmt.valid_future = 1
            return 1
        return 0

    def get_features(self):
        """Return list of features enabled by future statements"""
        return self.found.keys()


class BadFutureParser(ASTVisitor):
    """Check for invalid future statements"""

    def visitImportFrom(self, node):
        if hasattr(node, "valid_future"):
            return
        if node.module != "__future__":
            return
        raise SyntaxError(
            "from __future__ imports must occur at the beginning of the file"
        )


def find_futures(node):
    p1 = FutureParser()
    p2 = BadFutureParser()
    walk(node, p1)
    walk(node, p2)
    return p1.get_features()
