<?php

namespace Illuminate\Http;

use JsonSerializable;
use InvalidArgumentException;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Contracts\Support\Arrayable;
use Symfony\Component\HttpFoundation\JsonResponse as BaseJsonResponse;

class JsonResponse extends BaseJsonResponse
{// a json response  extends base Json response
    use ResponseTrait;// use Response Trait
   // a trait

    /**
     * The json encoding options.
     *
     * @var int
     */
    protected $jsonOptions;// The json encoding options

    /**
     * Constructor.
     *
     * @param  mixed  $data
     * @param  int    $status
     * @param  array  $headers
     * @param  int    $options
     */
    public function __construct($data = null, $status = 200, $headers = [], $options = 0)
    {
        $this->jsonOptions = $options;

        parent::__construct($data, $status, $headers);
    }// a constructor about instance of the response
   // more type response

    /**
     * Get the json_decoded data from the response.
     *
     * @param  bool  $assoc
     * @param  int   $depth
     * @return mixed
     */
    public function getData($assoc = false, $depth = 512)
    {
        return json_decode($this->data, $assoc, $depth);// a json decode method
    }// Get the json_decoded data from the response.

    /**
     * {@inheritdoc}
     */
    public function setData($data = [])
    {
        if ($data instanceof Arrayable) {
            $this->data = json_encode($data->toArray(), $this->jsonOptions);// array
        } elseif ($data instanceof Jsonable) {
            $this->data = $data->toJson($this->jsonOptions);// to json
        } elseif ($data instanceof JsonSerializable) {
            $this->data = json_encode($data->jsonSerialize(), $this->jsonOptions);// to serialize
        } else {
            $this->data = json_encode($data, $this->jsonOptions);
        }

        if (JSON_ERROR_NONE !== json_last_error()) {
            throw new InvalidArgumentException(json_last_error_msg());
        }// JSON_ERROR_NONE

        return $this->update();
    }// set Data inert into the

    /**
     * Get the JSON encoding options.
     *
     * @return int
     */
    public function getJsonOptions()
    {
        return $this->jsonOptions;
    }// get Json Options

    /**
     * Set the JSON encoding options.
     *
     * @param  int  $options
     * @return mixed
     */
    public function setJsonOptions($options)
    {
        $this->jsonOptions = $options;// set the options

        return $this->setData($this->getData());// and set Data
    }// set Json Options
}