import { queenApi } from "queenjs";
import { connect, StringCodec, Empty, ErrorCode } from "nats.ws";
import { Controller } from "../core/controller";
import { useCtx } from "../ctx";

export class NatsController extends Controller {
 
  _conn: any;
  _isConned = false;
  _startInit = false;

  async onReady() {
      await this.initConn();
  }

  async initConn() {
    if (this._startInit) return;
    this._startInit = true;

    const {deviceCtrl} = useCtx()

    const profile = deviceCtrl.profile;

    if (!profile.wsPort) return;
    
    
    const wsHost = `nats://localhost:${profile.wsPort}`
    console.log("ws host=>", wsHost);
    let ret = false;

    try {
      this._conn = await connect({ servers: wsHost });
      this._isConned = !!this._conn;

      ret = true;
    } catch (error) {
      console.log(error);
    }

    this._startInit = false;
    return ret;
  }
  
  async GetConn() {
    return this._conn;
  }

  async subscribe(subject: string, callback: any, options:any = {}) {
  
    if (!this._isConned) {
      console.error("建立连接失败");
      return;
    }

    const sc = StringCodec();
    const sub = this._conn.subscribe(subject, options);

    (async () => {
      for await (const m of sub) {
        const ret = sc.decode(m.data);
        console.log(subject, "=>recieved");
        try {
          if (ret) {
            const msg = JSON.parse(ret);
            const out = await callback(msg);
            m.respond(sc.encode(out))

          } else {
            const out = await callback(ret);
            m.respond(sc.encode(out))
          }
        } catch (error) {
          console.log(subject, "=>recieved json parse eror", ret);
          console.log(error);
        }
      }
      console.log(subject, "subscription closed");
    })();
    return function () {
      sub.unsubscribe();
    };
  }

  async requestApi(subject: string, data?: any, timeout?: number) {
    if (!this._isConned) return;

    const ret = await this.request(subject, data, timeout);
    console.log("request api=>", ret);

    if (ret.error || (ret.result.ErrorNo && ret.result.ErrorNo != 200)) {
      queenApi.messageError(ret.error || ret.result.ErrorDesc);
      return;
    }
    try {
      const retJson = ret.result.Result;
      if (!retJson) return;
      if (retJson[0] != "{" && retJson[0] != "[") return retJson;
      return JSON.parse(retJson);
    } catch (error) {
      console.log(ret);
      console.error(error);
    }
  }
  
  async publish(subject:string, value:string) {
    
    if (!this._isConned) {return}

    const sc = StringCodec();

    return await this._conn.publish(subject,  sc.encode(value));
  }

  async request(subject: string, data?: any, timeout?: number) {

    const ret: { error: string; result: any } = { error: "", result: null };
    if (!this._isConned) {
      console.error("建立连接失败");
      ret.error = "建立连接失败";

      queenApi.showConfirm({
        title: "数据请求失败",
        content: "请求数据失败,请重新启动后再试",
        type: "danger",
      });
      return ret;
    }

    const sc = StringCodec();
    try {
      let req = Empty;
      if (data) {
        if (typeof data != "string") {
          req = sc.encode(JSON.stringify(data));
        } else {
          req = sc.encode(data);
        }
      }
      const options = { timeout: 5000 };
      if (timeout) {
        options.timeout = timeout;
      }
      const m = await this._conn.request(subject, req, options);
      let payload = sc.decode(m.data);
      try {
        payload = JSON.parse(payload);
        console.log("m=>", payload);
      } catch (error) {
        console.log(error);
      }
      ret.result = payload;
    } catch (error: any) {
      console.error(error);
      ret.error = error.message || "请求" + subject + "出错";
      if (ret.error == "503") {
        //NoResponders
        ret.error = "网路异常,请重启服务";
      }
    }
    return ret;
  }

  close() {
    if (!this._isConned) {
      return;
    }
    return this._conn.close();
  }
}
