
#include "modbus_textsensor.h"
#include "esphome/core/log.h"

namespace esphome::modbus_controller {

static const char *const TAG = "modbus_controller.text_sensor";

void ModbusTextSensor::dump_config() { LOG_TEXT_SENSOR("", "Modbus Controller Text Sensor", this); }

void ModbusTextSensor::parse_and_publish(std::span<const uint8_t> data) {
  std::string output_str{};
  uint8_t items_left = this->response_bytes;
  const size_t start_offset = this->offset;
  size_t index = start_offset;
  while ((items_left > 0) && index < data.size()) {
    uint8_t b = data[index];
    switch (this->encode_) {
      case RawEncoding::HEXBYTES: {
        // max 3: 2 hex digits + null
        char hex_buf[3];
        snprintf(hex_buf, sizeof(hex_buf), "%02x", b);
        output_str += hex_buf;
        break;
      }
      case RawEncoding::COMMA: {
        // max 5: optional ','(1) + uint8(3) + null, for both ",%d" and "%d"
        char dec_buf[5];
        snprintf(dec_buf, sizeof(dec_buf), index != start_offset ? ",%d" : "%d", b);
        output_str += dec_buf;
        break;
      }
      case RawEncoding::ANSI:
        if (b < 0x20)
          break;
      // FALLTHROUGH
      // Anything else no encoding
      default:
        output_str += (char) b;
        break;
    }
    items_left--;
    index++;
  }

  // Is there a lambda registered
  // call it with the pre converted value and the raw data array
  if (this->transform_func_.has_value()) {
    // the lambda can parse the response itself
    auto val = (*this->transform_func_)(this, output_str, data);
    if (val.has_value()) {
      ESP_LOGV(TAG, "Value overwritten by lambda");
      output_str = val.value();
    }
  }
  this->publish_state(output_str);
}

}  // namespace esphome::modbus_controller
