private function write(string $data, bool $close = false): Promise
    {
        if ($this->status & self::CLOSED_WR) {
            return new Failure(new ClientException("The client disconnected"));
        }

        if (!$this->writeDeferred) {
            $bytesWritten = @\fwrite($this->socket, $data);

            if ($bytesWritten === false) {
                $this->close();
                return new Failure(new ClientException("The client disconnected"));
            }

            if ($bytesWritten !== 0) {
                $this->timeoutCache->renew($this->id);
            }

            if ($bytesWritten === \strlen($data)) {
                if ($close) {
                    $this->close();
                }

                return new Success;
            }

            $this->writeDeferred = new Deferred;
            $data = \substr($data, $bytesWritten);
        }

        $this->writeBuffer .= $data;

        Loop::enable($this->writeWatcher);

        $promise = $this->writeDeferred->promise();

        if ($close) {
            Loop::cancel($this->readWatcher);
            $this->status |= self::CLOSED_WR;
            $promise->onResolve([$this, "close"]);
        }

        return $promise;
    }