import {
  RSocketClient,
  JsonSerializer,
  IdentitySerializer,
  Encodable,
  encodeAndAddWellKnownMetadata,
  encodeAndAddCustomMetadata,
  MESSAGE_RSOCKET_ROUTING,
  MESSAGE_RSOCKET_COMPOSITE_METADATA,
  TEXT_PLAIN,
  WellKnownMimeType,
  APPLICATION_JSON,
} from "rsocket-core";
// MESSAGE_RSOCKET_AUTHENTICATION("message/x.rsocket.authentication.v0", (byte) 0x7C)
import { EchoResponder } from "./EchoResponder";
import { every } from "rsocket-flowable";
import RSocketTcpClient from "rsocket-tcp-client";
import RSocketWebSocketClient from "rsocket-websocket-client";

const maxRSocketRequestN = 2147483647;
const keepAlive = 60000;
const lifetime = 180000;
const dataMimeType = "application/octet-stream";
const metadataMimeType = MESSAGE_RSOCKET_COMPOSITE_METADATA.string;

const address = { host: "localhost", port: 7000 };

const messageReceiver = (payload) => {
  //do what you want to do with received message
  if ((payload.metadata as string).slice(1) == "user.queue.reply")
    console.log("YES");
  else console.log("No");
  console.log((payload.metadata as string).slice(1));
  console.log(payload);
};
const responder = new EchoResponder(messageReceiver);

function getClientTransport(host: string, port: number) {
  return new RSocketWebSocketClient({
    url: `ws://${host}:${port}/client-id`,
  });
}

interface Message {
  toUser: string;
  fromUser: string;
  message: string;
}

const client = new RSocketClient<Object, Encodable>({
  // send/receive JSON objects instead of strings/buffers
  serializers: {
    data: JsonSerializer,
    metadata: IdentitySerializer,
  },
  setup: {
    //for connection mapping on server
    payload: {
      data: { id: 1234, name: "John" },
      // metadata: encodeAndAddWellKnownMetadata(
      //   encodeAndAddCustomMetadata(
      //     Buffer.alloc(0),
      //     "message/x.rsocket.authentication.v0",
      //     Buffer.from("Hello World")
      //   ),
      //   MESSAGE_RSOCKET_ROUTING,
      //   Buffer.from(String.fromCharCode("client-id2".length) + "client-id2")
      // ),
      metadata: String.fromCharCode("client-id2".length) + "client-id2"
    },
    // ms btw sending keepalive to server
    keepAlive: 60000,

    // ms timeout if no keepalive response
    lifetime: 180000,

    // format of `data`
    dataMimeType: "application/json",

    // format of `metadata`
    metadataMimeType: "message/x.rsocket.routing.v0",
  },
  responder: responder,
  transport: getClientTransport(address.host, address.port),
});
const route = "user.queue.reply";
const sendRoute = "private.news.2";
client.connect().subscribe({
  onComplete: (rSocket) => {
    every(1000).subscribe({
      onNext: (time) => {
        console.log(`Requester availability: ${rSocket.availability()}`);
        // rSocket
        //   .requestResponse({
        //     data: time.toString(),
        //     metadata: "",
        //   })
        //   .subscribe({
        //     onComplete: (response) => {
        //       const data = response.data;
        //       if (data) {
        //         console.log(`Requester response: ${data}`);
        //       }
        //     },
        //     onError: (error) =>
        //       console.log(`Requester error: ${error.message}`),
        //   });

        // rSocket
        //   .requestStream({
        //     metadata: String.fromCharCode(route.length) + route,
        //   })
        //   .subscribe({
        //     onComplete: () => console.log("Request-stream completed"),
        //     onError: (error) =>
        //       console.error(`Request-stream error:${error.message}`),
        //     onNext: (value) => console.log("%s", value.data),
        //     onSubscribe: (sub) => sub.request(maxRSocketRequestN),
        //   });

        rSocket.fireAndForget({
          data: <Message>{ toUser: "4567", fromUser: "1234", message: "testHello" },
          metadata: String.fromCharCode(sendRoute.length) + sendRoute,
        });
        // S APPLICATION_JSON.string
      },
      onSubscribe: (subscription) =>
        subscription.request(Number.MAX_SAFE_INTEGER),
    });
    console.log("RSocket completed");

    rSocket.connectionStatus().subscribe((status) => {
      console.log("Connection status:", status);
    });
  },
  onError: (error) => console.log(`RSocket error: ${error.message}`),
});

// setTimeout(() => {}, 360000);
