#! /usr/bin/env ruby
# frozen_string_literal: true

require 'json'

class MacOSBatteryExporter
  def export
    puts metrics
  end

  def metrics
    <<~METRICS
      # HELP node_battery_charge_percent Battery charge percent
      # TYPE node_battery_charge_percent gauge
      node_battery_charge_percent{serial="#{battery_serial_number}"} #{charge_percentage}
      # HELP node_battery_charge_ampere Battery charge ampere
      # TYPE node_battery_charge_ampere gauge
      node_battery_charge_ampere{serial="#{battery_serial_number}"} #{charge_info['sppower_battery_current_capacity'] / 1000.0}
      # HELP node_battery_full_charge_ampere Battery full charge capacity
      # TYPE node_battery_full_charge_ampere gauge
      node_battery_full_charge_ampere{serial="#{battery_serial_number}"} #{charge_info['sppower_battery_max_capacity'] / 1000.0}
      # HELP node_battery_current_flow_ampere Current flow of ampere in (+) or out (-) of battery
      # TYPE node_battery_current_flow_ampere gauge
      node_battery_current_flow_ampere{serial="#{battery_serial_number}"} #{battery_info['sppower_current_amperage'] / 1000.0}
      # HELP node_battery_charger_connected Is charger connected?
      # TYPE node_battery_charger_connected gauge
      node_battery_charger_connected{serial="#{battery_serial_number}"} #{ac_charger_info['sppower_battery_charger_connected'] == 'TRUE' ? 1.0 : 0.0}
      # HELP node_battery_is_charging Is charger connected?
      # TYPE node_battery_is_charging gauge
      node_battery_is_charging{serial="#{battery_serial_number}"} #{ac_charger_info['sppower_battery_is_charging'] == 'TRUE' ? 1.0 : 0.0}
      # HELP node_battery_charger_watts Watts provided by charger
      # TYPE node_battery_charger_watts gauge
      node_battery_charger_watts{serial="#{battery_serial_number}"} #{ac_charger_info['sppower_ac_charger_watts'].to_f}
      # HELP node_battery_fully_charged Is battery fully charged?
      # TYPE node_battery_fully_charged gauge
      node_battery_fully_charged{serial="#{battery_serial_number}"} #{ac_charger_info['sppower_battery_fully_charged'] == 'TRUE' ? 1.0 : 0.0}
      # HELP node_battery_cycle_count Battery cycle count
      # TYPE node_battery_cycle_count counter
      node_battery_cycle_count{serial="#{battery_serial_number}"} #{health_info['sppower_battery_cycle_count']}
    METRICS
  end

  def charge_percentage
    @charge_percentage ||=
      `pmset -g batt | grep -Eo '\\d+%' | cut -d% -f1`.strip
  end

  def battery_serial_number
    battery_info.dig(
      'sppower_battery_model_info',
      'sppower_battery_serial_number'
    )
  end

  def charge_info
    @charge_info ||= battery_info['sppower_battery_charge_info']
  end

  def health_info
    @health_info ||= battery_info['sppower_battery_health_info']
  end

  def battery_info
    @battery_info ||= power_data&.find do |v|
      v['_name'] == 'spbattery_information'
    end
  end

  def ac_charger_info
    @ac_charger_info ||= power_data&.find do |v|
      v['_name'] == 'sppower_ac_charger_information'
    end
  end

  def power_data
    @power_data ||= JSON.parse(`system_profiler SPPowerDataType -json`)
                        &.[]('SPPowerDataType')
  end
end

MacOSBatteryExporter.new.export if __FILE__ == $PROGRAM_NAME
