'use strict';
import GObject from 'gi://GObject';
import St from 'gi://St';
import Clutter from 'gi://Clutter';

import {
    hexToColor, setSourceColor, getInkBounds, addVectorImage, loadFileToCairoSurface
} from './colorHelpers.js';
import {VectorImages} from './circularBatteryVectorImages.js';


// Credits: to https://github.com/Deminder for this
// https://github.com/Deminder/battery-indicator-icon/blob/main/src/modules/drawicon.js

export const CircleBatteryIcon = GObject.registerClass({
    GTypeName: 'BluetoothBatteryMeter_CircleBatteryIcon',
}, class CircleBatteryIcon extends St.DrawingArea {
    _init(iconSize, deviceIcon, widgetInfo) {
        super._init({x_align: Clutter.ActorAlign.CENTER, y_align: Clutter.ActorAlign.CENTER});
        this.width = iconSize;
        this.height = iconSize;
        this._iconSize = iconSize;
        this._deviceIcon = deviceIcon;
        this._widgetInfo = widgetInfo;
        this._extPath = widgetInfo.extPath;
        this._loadDeviceIcon();
    }

    _loadDeviceIcon() {
        this._cairoCacheSurface = null;
        this._transform = {};

        const intendedIconSize = 15;
        const svgSize = 16;
        const unscaledCanvasSize = 32;

        const iconFolder = `${this._extPath}/icons/hicolor/scalable/actions`;
        const filePath = `${iconFolder}/bbm-${this._deviceIcon}-symbolic.svg`;

        const inkRect =  getInkBounds(filePath, svgSize);
        if (!inkRect)
            return;

        const intendedScale = intendedIconSize / svgSize;
        const displayScale = this._iconSize / unscaledCanvasSize;
        const textureScale = Math.ceil(displayScale);
        const scale = displayScale * intendedScale / textureScale;
        const unscaledOffsetXY = (unscaledCanvasSize - intendedIconSize) / 2;
        const offsetXY = unscaledOffsetXY * textureScale / intendedScale;

        this._transform.scale = scale;
        this._transform.offsetXY = offsetXY;
        this._transform.chargingStatusScale = displayScale;

        this._cairoCacheSurface = loadFileToCairoSurface(filePath, textureScale);
    }

    _assignWidgetColor() {
        const themeColors = this.get_theme_node().get_icon_colors();
        const foregroundColor = themeColors.foreground;
        const successColor =  themeColors.success;
        const warningColor =  themeColors.warning;
        const errorColor =  themeColors.error;
        const baseLevelColor = foregroundColor.copy();
        baseLevelColor.alpha *= 0.5;

        let fillLevelColor;
        let chargingIconColor = foregroundColor;
        const disconnectedIconColor = errorColor;
        if (this._widgetInfo.circleWidgetColor === 0) {
            fillLevelColor = this._percentage > 20 ? foregroundColor : warningColor;
            chargingIconColor = successColor;
        } else if (this._widgetInfo.circleWidgetColor === 1) {
            fillLevelColor = this._percentage > 20 ? successColor : warningColor;
        } else {
            const idx = Math.ceil(this._percentage / 10) - 1;
            const fallbackColor = this._percentage > 20 ? successColor : warningColor;
            const hex = this._widgetInfo.circleWidgetCustomColors[idx] ?? fallbackColor;
            fillLevelColor = hexToColor(hex);
        }
        return {
            foregroundColor, fillLevelColor, baseLevelColor,
            chargingIconColor, disconnectedIconColor,
        };
    }

    updateValues(percentage, status) {
        this._status = status;
        this._percentage = percentage;
        this.queue_repaint();
    }

    _drawIcon(cr) {
        cr.save();
        cr.scale(this._transform.scale, this._transform.scale);
        cr.translate(this._transform.offsetXY, this._transform.offsetXY);
        setSourceColor(cr, this._colors.foregroundColor);
        cr.maskSurface(this._cairoCacheSurface, 0, 0);
        cr.restore();
    }

    _drawCircle(cr) {
        const size = this._iconSize;
        const one = size / 16;
        const strokeWidth = 1.8 * one;
        const p = this._percentage <= 0 ? 0 : this._percentage / 100;
        const radius = (size - strokeWidth) / 2;
        const [cw, ch] = [size / 2, size / 2];
        cr.save();
        setSourceColor(cr, this._colors.baseLevelColor);
        cr.setLineWidth(strokeWidth);
        cr.translate(cw, ch);
        cr.arc(0, 0, radius, 0, 2 * Math.PI);
        cr.stroke();

        setSourceColor(cr, this._colors.fillLevelColor);
        const angleOffset = -0.5 * Math.PI;
        cr.arc(0, 0, radius, angleOffset, angleOffset + p * 2 * Math.PI);
        cr.stroke();
        cr.restore();
    }

    _drawChargingStatusVectors(cr) {
        if (this._status !== 'disconnected' && this._status !== 'charging')
            return;

        cr.scale(this._transform.chargingStatusScale, this._transform.chargingStatusScale);

        const modelPath = VectorImages[this._deviceIcon];
        const chargingPath = VectorImages['charging-bolt'];
        const disconnectedPath = VectorImages['disconnected'];

        addVectorImage(cr, modelPath, this._colors.foregroundColor);

        if (this._status === 'disconnected') {
            cr.fill();
            addVectorImage(cr, disconnectedPath, this._colors.disconnectedIconColor);
        } else if (this._status === 'charging') {
            addVectorImage(cr, chargingPath, this._colors.chargingIconColor);
        }
        cr.fill();
    }

    vfunc_repaint() {
        if (!this._cairoCacheSurface)
            return;

        const [w, h] = this.get_surface_size();
        if (w === 0 || h === 0)
            return;

        if (this._transform.scale === undefined || this._transform.offsetXY === undefined ||
                this._transform.chargingStatusScale === undefined)
            return;

        this._colors = this._assignWidgetColor();
        const cr = this.get_context();
        this._drawIcon(cr);
        this._drawCircle(cr);
        cr.$dispose();
    }
}
);


