<?PHP

class JsonHelper
{

    private $Data;
    private $Warnings;

    public function __construct()
    {
        $this->Data = array();
        $this->Warnings = array();
    }

    public function AddDatum($Key, $Value)
    {
        $this->Data[$Key] = $Value;
    }

    public function AddWarning($Message)
    {
        $this->Warnings[] = strval($Message);
    }

    public function Error($Message)
    {
        $this->SendResult($this->GenerateResult("ERROR", $Message));
    }

    public function Success($Message="")
    {
        $this->SendResult($this->GenerateResult("OK", $Message));
    }

    private function SendResult(array $Result)
    {
        global $SysConfig;
        header("Content-Type: application/json; charset="
            .$SysConfig->DefaultCharacterSet(), TRUE);
        $this->PrintArrayToJson($Result);
    }

    private function GenerateResult($State, $Message)
    {
        return array(
            "data" => $this->Data,
            "status" => array(
                "state" => strval($State),
                "message" => strval($Message),
                "numWarnings" => count($this->Warnings),
                "warnings" => $this->Warnings));
    }

    private function PrintArrayToJson(array $Array)
    {
        # variables needed for printing commas if necessary
        $Offset = 0;
        $Count = count($Array);

        # determine whether or not we have a true array or a hash map
        $TrueArray = TRUE;
        for ($i = 0, reset($Array); $i < count($Array); $i++, next($Array))
        {
            if (key($Array) !== $i)
            {
                $TrueArray = FALSE;
                break;
            }
        }

        # opening bracket
        print ($TrueArray) ? "[" : "{";

        # print each member
        foreach ($Array as $key => $value)
        {
            # replacements so we can escape strings and replace smart quotes
            static $Replace = array(
                array("\\", "/", "\n", "\t", "\r", "\b", "\f", '"', "", "", "", "", ""),
                array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"', "'", "'", '\"', '\"', '-'));

            # print key if a hash map
            if (!$TrueArray)
            {
                # escape, remove smart quotes, and print the key
                print '"'.str_replace($Replace[0], $Replace[1], $key).'":';
            }

            # scalar values (int, float, string, or boolean)
            if (is_scalar($value))
            {
                # numeric (i.e., float, int, or float/int string)
                if (is_numeric($value))
                {
                    print $value;
                }

                # string
                else if (is_string($value))
                {
                    # escape, remove smart quotes, and print the value
                    print '"'.str_replace($Replace[0], $Replace[1], $value).'"';
                }

                # boolean true
                else if ($value === TRUE)
                {
                    print "true";
                }

                # boolean false
                else if ($value === FALSE)
                {
                    print "false";
                }
            }

            # recur if the value is an array
            else if (is_array($value))
            {
                $this->PrintArrayToJson($value);
            }

            # null
            else if (is_null($value))
            {
                print "null";
            }

            # object, just print the name and don't possibly expose secret details
            else if (is_object($value))
            {
                print '"object('.get_class($value).')"';
            }

            # resource, just print the name and don't possibly expose secret details
            else
            {
                print '"resource('.get_resource_type($value).')"';
            }

            # print comma if necessary
            if (++$Offset < $Count) {  print ",";  }
        }

        # closing bracket
        print ($TrueArray) ? "]" : "}";
    }

}

?>
