<?php


namespace Mainto\RpcServer\Util\Net\Conn;


use Mainto\RpcServer\Util\Net\Address;
use Mainto\RpcServer\Util\Net\Conn;
use Mainto\RpcServer\Util\Net\Exceptions\ServerNotFoundException;
use RuntimeException;

class UnixConn implements Conn {
    /**
     * Socket
     */
    private $socket;

    /**
     * @var Address\UnixAddress
     */
    private Address\UnixAddress $remoteAddr;

    public static function newConnByAddress($address) {
        if (!file_exists($address)) {
            throw new ServerNotFoundException();
        }

        $socket = @socket_create(AF_UNIX, SOCK_STREAM, 0);
        if (!$socket) {
            throw new RuntimeException("create unix error");
        }

        if (!@socket_connect($socket, $address)) {
            throw new RuntimeException("connect unix error:" . socket_last_error($socket));
        }

        $conn = new self($socket);
        $conn->remoteAddr = new Address\UnixAddress($address);

        return $conn;
    }

    public function __construct ($socket) {
        $this->socket = $socket;
    }

    public function close () {
        @socket_close($this->socket);
    }

    public function read (int $size): ?string {
        if ($size === 0) {
            return null;
        }
        $res = socket_read($this->socket, $size);
        if ($res === false || $res === "") {
            throw new RuntimeException(sprintf("socket read [%s] error: ".socket_last_error($this->socket) . " size: ". $size, $res === false ? 'false' : 'empty'));
        }

        return $res;
    }

    public function write (string $p): int {
        return socket_write($this->socket, $p);
    }

    public function localAddr (): Address {
        // TODO: Implement localAddr() method.
    }

    public function remoteAddr (): Address {
        return $this->remoteAddr;
    }
}