#
# General code for JSBeautifier unpackers infrastructure. See README.specs
#     written by Stefano Sanfilippo <a.little.coder@gmail.com>
#

"""General code for JSBeautifier unpackers infrastructure."""

import pkgutil
import re
from jsbeautifier.unpackers import evalbased

# NOTE: AT THE MOMENT, IT IS DEACTIVATED FOR YOUR SECURITY: it runs js!
BLACKLIST = ["jsbeautifier.unpackers.evalbased"]


class UnpackingError(Exception):
    """Badly packed source or general error. Argument is a
    meaningful description."""

    pass


def getunpackers():
    """Scans the unpackers dir, finds unpackers and add them to UNPACKERS list.
    An unpacker will be loaded only if it is a valid python module (name must
    adhere to naming conventions) and it is not blacklisted (i.e. inserted
    into BLACKLIST."""
    path = __path__
    prefix = __name__ + "."
    unpackers = []
    interface = ["unpack", "detect", "PRIORITY"]
    for _importer, modname, _ispkg in pkgutil.iter_modules(path, prefix):
        if "tests" not in modname and modname not in BLACKLIST:
            try:
                module = __import__(modname, fromlist=interface)
            except ImportError:
                raise UnpackingError("Bad unpacker: %s" % modname)
            else:
                unpackers.append(module)

    return sorted(unpackers, key=lambda mod: mod.PRIORITY)


UNPACKERS = getunpackers()


def run(source, evalcode=False):
    """Runs the applicable unpackers and return unpacked source as a string."""
    for unpacker in [mod for mod in UNPACKERS if mod.detect(source)]:
        source = unpacker.unpack(source)
    if evalcode and evalbased.detect(source):
        source = evalbased.unpack(source)
    return source


def filtercomments(source):
    """NOT USED: strips trailing comments and put them at the top."""
    trailing_comments = []
    comment = True

    while comment:
        if re.search(r"^\s*\/\*", source):
            comment = source[0, source.index("*/") + 2]
        elif re.search(r"^\s*\/\/", source):
            comment = re.search(r"^\s*\/\/", source).group(0)
        else:
            comment = None

        if comment:
            source = re.sub(r"^\s+", "", source[len(comment) :])
            trailing_comments.append(comment)

    return "\n".join(trailing_comments) + source
