

import collections

# TODO: remove "PHP" prefix from function names

def to_php_identifier(s):
    """ Turn 's' into a valid PHP identifier. """
    # TODO: more rules
    return s.replace("-", "_")

class PHPString:
    def __init__(self, value):
        self.value = value
    def get_value_escaped(self):
        # TODO: more rules
        return self.value.replace("\\", "\\\\").replace("'", "\\'")
    def __str__(self):
        return "'" + self.get_value_escaped() + "'"

class PHPArray(list):
    def __init__(self, values=[], multiline=False):
        super(PHPArray, self).__init__(values)
        self.multiline = multiline
    def __str__(self):
        if self.multiline:
            elem_sep = ",\n"
        else:
            elem_sep = ", "
        return "array({})".format(elem_sep.join(map(str, self)))

class PHPDict(collections.OrderedDict):
    def __init__(self, items={}):
        super(PHPDict, self).__init__(items)
    def __str__(self):
        elems = []
        for (k, v) in list(self.items()):
            elems.append("{} => {}".format(PHPLiteral(k), v))
        return "array({})".format(", ".join(elems))

class PHPLiteral:
    def __init__(self, value):
        self.value = value
        if isinstance(value, str):
            self.value_php = str(PHPString(value))
        # bool must be checked before int, see
        # https://www.peterbe.com/plog/bool-is-int
        elif isinstance(value, bool):
            self.value_php = "true" if value else "false"
        elif isinstance(value, int):
            self.value_php = str(value)
        elif value is None:
            self.value_php = "null"
        else:
            # TODO: more types
            assert False, "Unknown literal type."
    def __str__(self):
        return self.value_php
    def __repr__(self):
        return repr(self.value)

class PHPFunctionCall:
    def __init__(self, function, *args):
        self.function = function
        self.args = args
    def __str__(self):
        return "{}({})".format(self.function, ", ".join(map(str, self.args)))
