#!/usr/bin/env python3
# Simple stat daemon
# Listens on a port for requests, responds with some basic information about the current state of the system.

import configparser
import os
import subprocess
import time
import argparse
import json
import http.server
import socketserver

def get_default_config():
    config = configparser.ConfigParser(interpolation=None)
    config['stat.system.uptime'] = {
        'command': 'uptime -p | cut -d" " -f2-',
        'format': '{}'
    }
    config['stat.cpu.temp'] = {
        'command': 'sensors -j | jq \'.["k10temp-pci-00c3"]["Tctl"]["temp1_input"]\'',
        'transform': 'lambda x: float(x)',
        'format': '{:.1f}',
        'unit': '°C',
        'historical': '1'
    }
    config['stat.cpu.act'] = {
        'command': 'top -bn1 | grep "Cpu(s)" | sed "s/.*, *\\([0-9.]*\\)%%* id.*/\\1/" | awk \'{print 100-$1}\'',
        'transform': 'lambda x: float(x)',
        'format': '{:.1f}',
        'unit': '%',
        'historical': '1'
    }
    config['stat.memory.pct'] = {
        'command': 'free | awk \'NR==2 {printf "%.1f", $3*100/$2}\'',
        'transform': 'lambda x: float(x)',
        'format': '{:.1f}',
        'unit': '%',
        'historical': '1'
    }
    config['stat.memory.total'] = {
        'command': 'free -m | awk \'NR==2 {print $2}\'',
        'transform': 'lambda x: int(x)',
        'format': '{}',
        'unit': 'MB'
    }
    config['stat.disk.root'] = {
        'command': 'df -h / | awk \'NR==2 {printf "%s/%s [%d%%]", $3, $2, $5}\'',
        'format': '{}'
    }
    return config

def get_config():
    config_home = os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config"))
    config_dir = os.path.join(config_home, "stats")
    if not os.path.exists(config_dir):
        os.makedirs(config_dir)
    config_file = os.path.join(config_dir, "config.ini")

    config = configparser.ConfigParser(interpolation=None)

    if os.path.exists(config_file):
        config.read(config_file)
    else:
        config = get_default_config()
        with open(config_file, 'w') as f:
            config.write(f)
    return config

def get_stats(config):
    stats = {}
    stat_sections = [s for s in config.sections() if s.startswith('stat.')]
    for section in stat_sections:
        # Split into category and name
        _, category, name = section.split('.')
        stat_config = config[section]
        if category not in stats:
            stats[category] = {}

        try:
            value = subprocess.getoutput(stat_config['command']).strip()

            transform = stat_config.get('transform', None)
            format = stat_config.get('format', None)
            unit = stat_config.get('unit', None)
            historical = stat_config.get('historical', False)
            if transform:
                transform_func = eval(transform)
                value = transform_func(value)
            if format:
                value = format.format(value)
            data = {
                'value': value
            }
            if unit:
                data['unit'] = unit
            if historical:
                data['track'] = bool(historical)
            stats[category][name] = data

        except Exception as e:
            print(e)
            #stats[category][name] = f"Error: {str(e)}"
    return stats

class StatsHandler(http.server.SimpleHTTPRequestHandler):
    def do_GET(self):
        data = {
            'timestamp': time.time(),
            'stats': get_stats(get_config())
        }
        response = json.dumps(data).encode('utf-8')

        self.send_response(200)
        self.send_header('Content-Type', 'application/json')
        self.send_header('Content-Length', str(len(response)))
        self.end_headers()
        self.wfile.write(response)

class StatsServer(socketserver.TCPServer):
    allow_reuse_address = True

def main():
    parser = argparse.ArgumentParser(description='Stats HTTP Server')
    parser.add_argument('--port', type=int, default=5747, help='Port to listen on')
    parser.add_argument('--host', default='0.0.0.0', help='Host to bind to')
    args = parser.parse_args()

    with StatsServer((args.host, args.port), StatsHandler) as httpd:
        print(f"Serving stats on http://{args.host}:{args.port}")
        try:
            httpd.serve_forever()
        except KeyboardInterrupt:
            print("\nShutting down server...")
            httpd.server_close()

if __name__ == '__main__':
    main()
