const Desklet = imports.ui.desklet;
const St = imports.gi.St;
const GLib = imports.gi.GLib;
const Mainloop = imports.mainloop;
const Lang = imports.lang;
const Settings = imports.ui.settings;

function NetworkMonitorDesklet(metadata, desklet_id) {
    this._init(metadata, desklet_id);
}

NetworkMonitorDesklet.prototype = {
    __proto__: Desklet.Desklet.prototype,

    _init: function(metadata, desklet_id) {
        Desklet.Desklet.prototype._init.call(this, metadata, desklet_id);

        this.metadata = metadata;
        this.desklet_id = desklet_id;

        // Initialize settings with default values
        this.network_interface = 'auto';
        this.theme = 'dark';
        this.font_size = 13;
        this.title_font_size = 16;
        this.update_interval = 1000;
        this.show_title = true;
        this.show_interface = true;

        // Bind settings
        this.settings = new Settings.DeskletSettings(this, this.metadata.uuid, this.desklet_id);
        this.settings.bindProperty(Settings.BindingDirection.IN,
            "network-interface", "network_interface", this.on_settings_changed, null);
        this.settings.bindProperty(Settings.BindingDirection.IN,
            "theme", "theme", this.on_settings_changed, null);
        this.settings.bindProperty(Settings.BindingDirection.IN,
            "font-size", "font_size", this.on_settings_changed, null);
        this.settings.bindProperty(Settings.BindingDirection.IN,
            "title-font-size", "title_font_size", this.on_settings_changed, null);
        this.settings.bindProperty(Settings.BindingDirection.IN,
            "update-interval", "update_interval", this.on_settings_changed, null);
        this.settings.bindProperty(Settings.BindingDirection.IN,
            "show-title", "show_title", this.on_settings_changed, null);
        this.settings.bindProperty(Settings.BindingDirection.IN,
            "show-interface", "show_interface", this.on_settings_changed, null);

        // Initialize stats
        this.prev_rx_bytes = 0;
        this.prev_tx_bytes = 0;
        this.current_interface = null;
        this.timeout = null;

        this.setupUI();
        this.detectActiveInterface();
        this.updateStats();
    },

    setupUI: function() {
        // Calculate container width based on font size
        // Base width: 300px, add 10px for every pt above 13
        let containerWidth = 300 + Math.max(0, (this.font_size - 13) * 10);

        // Main container
        let containerClass = this.theme === 'light' ? 'network-monitor-container-light' : 'network-monitor-container';
        this.window = new St.BoxLayout({
            vertical: true,
            style_class: containerClass
        });
        this.window.set_style('min-width: ' + containerWidth + 'px;');

        // Title
        if (this.show_title) {
            let titleClass = this.theme === 'light' ? 'network-monitor-title-light' : 'network-monitor-title';
            this.titleLabel = new St.Label({
                text: 'Network Monitor',
                style_class: titleClass
            });
            this.titleLabel.set_style('font-size: ' + this.title_font_size + 'pt;');
            this.window.add(this.titleLabel);
        }

        // Interface label
        if (this.show_interface) {
            let interfaceClass = this.theme === 'light' ? 'network-monitor-interface-light' : 'network-monitor-interface';
            this.interfaceLabel = new St.Label({
                text: 'Interface: detecting...',
                style_class: interfaceClass
            });
            this.window.add(this.interfaceLabel);
        }

        // Download speed
        let downloadClass = this.theme === 'light' ? 'network-monitor-download-light' : 'network-monitor-download';
        this.downloadLabel = new St.Label({
            text: 'Download: 0.00 KB/s',
            style_class: downloadClass
        });
        this.downloadLabel.set_style('font-size: ' + this.font_size + 'pt;');
        this.window.add(this.downloadLabel);

        // Upload speed
        let uploadClass = this.theme === 'light' ? 'network-monitor-upload-light' : 'network-monitor-upload';
        this.uploadLabel = new St.Label({
            text: 'Upload      : 0.00 KB/s',
            style_class: uploadClass
        });
        this.uploadLabel.set_style('font-size: ' + this.font_size + 'pt;');
        this.window.add(this.uploadLabel);

        this.setContent(this.window);
    },

    on_settings_changed: function() {
        // Stop current update loop
        if (this.timeout) {
            Mainloop.source_remove(this.timeout);
            this.timeout = null;
        }

        // Reset stats
        this.prev_rx_bytes = 0;
        this.prev_tx_bytes = 0;

        // Rebuild UI
        if (this.window) {
            this.window.destroy();
        }
        this.setupUI();
        this.detectActiveInterface();
        this.updateStats();
    },

    detectActiveInterface: function() {
        // Check if user specified a custom interface
        if (this.network_interface && this.network_interface !== 'auto') {
            let iface_path = '/sys/class/net/' + this.network_interface;
            if (GLib.file_test(iface_path, GLib.FileTest.EXISTS)) {
                this.current_interface = this.network_interface;
                if (this.show_interface && this.interfaceLabel) {
                    this.interfaceLabel.set_text('Interface: ' + this.current_interface);
                }
                return;
            }
        }

        // Auto-detect: Get default route to find active interface
        try {
            let output = GLib.spawn_command_line_sync('ip route show default');
            if (output[0]) {
                let output_str = output[1].toString();
                let match = output_str.match(/dev\s+(\S+)/);
                if (match && match[1]) {
                    this.current_interface = match[1];
                    if (this.show_interface && this.interfaceLabel) {
                        this.interfaceLabel.set_text('Interface: ' + this.current_interface);
                    }
                    return;
                }
            }
        } catch (e) {
            global.logError('Error detecting interface: ' + e);
        }

        // Fallback to common interface names
        let common_interfaces = ['wlan0', 'wlp3s0', 'eth0', 'enp0s3', 'eno1'];
        for (let i = 0; i < common_interfaces.length; i++) {
            let iface = common_interfaces[i];
            let iface_path = '/sys/class/net/' + iface;
            if (GLib.file_test(iface_path, GLib.FileTest.EXISTS)) {
                this.current_interface = iface;
                if (this.show_interface && this.interfaceLabel) {
                    this.interfaceLabel.set_text('Interface: ' + this.current_interface);
                }
                break;
            }
        }
    },

    getInterfaceStats: function() {
        if (!this.current_interface) {
            return { rx_bytes: 0, tx_bytes: 0 };
        }

        try {
            let rx_path = '/sys/class/net/' + this.current_interface + '/statistics/rx_bytes';
            let tx_path = '/sys/class/net/' + this.current_interface + '/statistics/tx_bytes';

            let rx_bytes = 0;
            let tx_bytes = 0;

            if (GLib.file_test(rx_path, GLib.FileTest.EXISTS)) {
                let rx_data = GLib.file_get_contents(rx_path);
                if (rx_data[0]) {
                    rx_bytes = parseInt(rx_data[1].toString().trim());
                }
            }

            if (GLib.file_test(tx_path, GLib.FileTest.EXISTS)) {
                let tx_data = GLib.file_get_contents(tx_path);
                if (tx_data[0]) {
                    tx_bytes = parseInt(tx_data[1].toString().trim());
                }
            }

            return { rx_bytes: rx_bytes, tx_bytes: tx_bytes };
        } catch (e) {
            global.logError('Error reading interface stats: ' + e);
            return { rx_bytes: 0, tx_bytes: 0 };
        }
    },

    formatSpeed: function(bytesPerSecond) {
        let kbps = bytesPerSecond / 1024;

        if (kbps < 1024) {
            return kbps.toFixed(2) + ' KB/s';
        } else {
            let mbps = kbps / 1024;
            return mbps.toFixed(2) + ' MB/s';
        }
    },

    updateStats: function() {
        let stats = this.getInterfaceStats();

        if (this.prev_rx_bytes > 0 && this.prev_tx_bytes > 0) {
            // Calculate bytes per second
            let rx_speed = (stats.rx_bytes - this.prev_rx_bytes) * (1000 / this.update_interval);
            let tx_speed = (stats.tx_bytes - this.prev_tx_bytes) * (1000 / this.update_interval);

            // Update labels
            if (this.downloadLabel) {
                this.downloadLabel.set_text('Download: ' + this.formatSpeed(rx_speed));
            }
            if (this.uploadLabel) {
                this.uploadLabel.set_text('Upload      : ' + this.formatSpeed(tx_speed));
            }
        }

        this.prev_rx_bytes = stats.rx_bytes;
        this.prev_tx_bytes = stats.tx_bytes;

        // Schedule next update
        this.timeout = Mainloop.timeout_add(this.update_interval, Lang.bind(this, this.updateStats));
    },

    on_desklet_removed: function() {
        if (this.timeout) {
            Mainloop.source_remove(this.timeout);
            this.timeout = null;
        }
    }
};

function main(metadata, desklet_id) {
    return new NetworkMonitorDesklet(metadata, desklet_id);
}
