<?php


namespace Mainto\RpcServer\RpcClient;


use Illuminate\Support\Facades\Log;
use Mainto\RpcServer\Protocol\Request\Request;
use Mainto\RpcServer\Protocol\Response\Response;
use Mainto\RpcServer\Protocol\Response\ResponseReader;
use Mainto\RpcServer\Util\IO\Closer;
use Mainto\RpcServer\Util\Net\Conn;
use Mainto\RpcServer\Util\Net\Net;
use Mainto\RpcServer\Util\OS;

class RpcClient implements Closer {
    public static string $baseUnixDir = "";

    protected Conn $conn;

    private int $pid;

    public function __construct (Conn $conn) {
        $this->pid = getmypid();

        $this->conn = $conn;
    }

    public static function setBaseUnixDir (string $socksDir) {
        self::$baseUnixDir = $socksDir;
    }

    public function Do (Request $request): Response {
        Log::debug("client send req", ['pid' => $this->pid, 'traceId' => $request->getTraceId(), 'data' => $request->toArray()]);
        $request->writeTo($this->conn);

        $response = ResponseReader::ReadResponseFrom($this->conn)->toResponse();
        Log::debug("client recv req", ['pid' => $this->pid, 'traceId' => $request->getTraceId(), 'data' => $response->toArray()]);

        return $response;
    }

    public function __destruct () {
        $this->close();
    }

    public function close () {
        $this->conn->close();
    }

    public static function getBaseUnixDir () {
        if (self::$baseUnixDir) {
            return self::$baseUnixDir;
        }

        $hostname = str_pad(config('rpc-server.sidecar.hostname'), 5, "0", STR_PAD_LEFT);

        return path_join(
            OS::getShmDir(),
            sprintf("%s-%s", substr(config('rpc-server.service_name'), 0, 4), substr($hostname, -5, 5))
        );
    }

    public static function getServiceClient (string $serviceName) {
        return new self(Net::dial('unix', path_join(self::getBaseUnixDir(), 'rpc_services', "$serviceName.sock")));
    }

    public static function getMessageQueueClient () {
        return new self(Net::dial("unix", path_join(self::getBaseUnixDir(), 'mq.sock')));
    }

    public static function getSettingClient () {
        return new self(Net::dial("unix", path_join(self::getBaseUnixDir(), 'setting.sock')));
    }

    public static function getSLSClient () {
        return new self(Net::dial("unix", path_join(self::getBaseUnixDir(), 'sls.sock')));
    }
}