const { outputUtils } = require('generalFunctions');
const Specific = require('./specificClass');

class nodeClass {
  constructor(uiConfig, RED, nodeInstance, nameOfNode) {
    this.node = nodeInstance;
    this.RED = RED;
    this.name = nameOfNode;
    this.source = null;
    this.config = null;

    this._loadConfig(uiConfig);
    this._setupSpecificClass();
    this._attachInputHandler();
    this._attachCloseHandler();
  }

  _loadConfig(uiConfig) {
    this.config = {
      general: {
        name: uiConfig.name || this.name,
        logging: {
          enabled: uiConfig.enableLog,
          logLevel: uiConfig.logLevel || 'info',
        },
      },
      grafanaConnector: {
        protocol: uiConfig.protocol || 'http',
        host: uiConfig.host || 'localhost',
        port: Number(uiConfig.port || 3000),
        bearerToken: uiConfig.bearerToken || '',
      },
    };

    this._output = new outputUtils();
  }

  _setupSpecificClass() {
    this.source = new Specific(this.config);
    this.node.source = this.source;
  }

  _attachInputHandler() {
    this.node.on('input', async (msg, send, done) => {
      try {
        if (msg.topic !== 'registerChild') {
          done();
          return;
        }

        const childId = msg.payload;
        const childObj = this.RED.nodes.getNode(childId);
        const childSource = childObj?.source;
        if (!childSource?.config) {
          throw new Error(`Missing child source/config for id=${childId}`);
        }

        const dashboards = this.source.generateDashboardsForGraph(childSource, {
          includeChildren: Boolean(msg.includeChildren ?? true),
        });

        const url = this.source.grafanaUpsertUrl();
        const headers = {
          Accept: 'application/json',
          'Content-Type': 'application/json',
        };
        if (this.config.grafanaConnector.bearerToken) {
          headers.Authorization = `Bearer ${this.config.grafanaConnector.bearerToken}`;
        }

        for (const dash of dashboards) {
          const payload = this.source.buildUpsertRequest({ dashboard: dash.dashboard, folderId: 0, overwrite: true });
          send({
            topic: 'grafana.dashboard.upsert',
            url,
            method: 'POST',
            headers,
            payload,
            meta: {
              nodeId: dash.nodeId,
              softwareType: dash.softwareType,
              uid: dash.uid,
              title: dash.title,
            },
          });
        }

        done();
      } catch (error) {
        this.node.status({ fill: 'red', shape: 'ring', text: 'dashboardapi error' });
        this.node.error(error?.message || error, msg);
        done(error);
      }
    });
  }

  _attachCloseHandler() {
    this.node.on('close', (done) => done());
  }
}

module.exports = nodeClass;

