using Php;

namespace PhpNative {
    private string var_dump_scalar (zval value) {
        switch (value.get_value_type ()) {
        case ValueType.NULL:
            return "NULL";
        case ValueType.BOOL:
            return "bool(%s)".printf (value.as_bool () ? "true" : "false");
        case ValueType.INT:
            return "int(%s)".printf (("%" + int64.FORMAT).printf (value.as_int ()));
        case ValueType.DOUBLE:
            return "float(%g)".printf (value.as_double ());
        case ValueType.STRING:
            return "string(%d) \"%s\"".printf (value.as_string ().length, value.as_string ());
        default:
            return "";
        }
    }

    private void append_var_dump (StringBuilder builder, zval value, int indent = 0) {
        string indent_text = "";
        for (int i = 0; i < indent; i++) {
            indent_text += " ";
        }

        switch (value.get_value_type ()) {
        case ValueType.ARRAY:
            builder.append ("array(%d) {".printf (value.count ()));
            builder.append_c ('\n');
            int index = 0;
            foreach (zval child in value.get_array_values ()) {
                builder.append ("%s  [%d]=>".printf (indent_text, index));
                builder.append_c ('\n');
                builder.append ("%s  ".printf (indent_text));
                append_var_dump (builder, child, indent + 4);
                if (child.get_value_type () == ValueType.ARRAY || child.get_value_type () == ValueType.OBJECT) {
                    builder.append_c ('\n');
                }
                index++;
            }
            builder.append ("%s}".printf (indent_text));
            break;
        case ValueType.OBJECT:
            builder.append ("object(stdClass)(%d) {".printf (value.count ()));
            builder.append_c ('\n');
            foreach (string key in value.get_object_keys ()) {
                zval child = value.get_object_values ()[key];
                builder.append ("%s  [\"%s\"]=>".printf (indent_text, key));
                builder.append_c ('\n');
                builder.append ("%s  ".printf (indent_text));
                append_var_dump (builder, child, indent + 4);
                if (child.get_value_type () == ValueType.ARRAY || child.get_value_type () == ValueType.OBJECT) {
                    builder.append_c ('\n');
                }
            }
            builder.append ("%s}".printf (indent_text));
            break;
        default:
            builder.append (var_dump_scalar (value));
            break;
        }
    }

    public string var_dump_static (zval value, string php_file, int php_line) throws Error {
        var builder = new StringBuilder ();
        append_var_dump (builder, value);
        builder.append_c ('\n');
        return builder.str;
    }

    public zval var_dump_zval (zval value, string php_file, int php_line) throws Error {
        echo_static (var_dump_static (value, php_file, php_line), php_file, php_line);
        return zval.null_value ();
    }
}
