// SPDX-License-Identifier: GPL-3.0-or-later

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright (C) 2013 - 2024, nymea GmbH
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
*
* This file is part of nymea-app.
*
* nymea-app is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* nymea-app is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with nymea-app. If not, see <https://www.gnu.org/licenses/>.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

pragma Singleton
import QtQuick 2.9
import Nymea 1.0
import QtCharts 2.2

Item {
    id: root

    function pad(num, size, base) {
        if (base == undefined) {
            base = 10
        }

        var trimmedNum = Math.floor(num)
        var decimals = num - trimmedNum
        var trimmedStr = "" + trimmedNum.toString(base)
        var str = "000000000" + trimmedStr
        str = str.substr(str.length - Math.max(size, trimmedStr.length));
        if (decimals !== 0) {
            str += "." + decimals.toString(base);
        }
        return str;
    }

    function interfaceListToDevicePage(interfaceList) {
        print("**** getting page for interfaces", interfaceList)
        var page;
        if (interfaceList.indexOf("media") >= 0) {
            page = "MediaThingPage.qml";
        } else if (interfaceList.indexOf("button") >= 0) {
            page = "ButtonThingPage.qml";
        } else if (interfaceList.indexOf("powerswitch") >= 0) {
            page = "ButtonThingPage.qml";
        } else if (interfaceList.indexOf("weather") >= 0) {
            page = "WeatherDevicePage.qml";
        } else if (interfaceList.indexOf("heating") >= 0) {
            page = "HeatingDevicePage.qml";
        } else if (interfaceList.indexOf("cooling") >= 0) {
            page = "CoolingThingPage.qml";
        } else if (interfaceList.indexOf("thermostat") >= 0) {
            page = "ThermostatDevicePage.qml";
        } else if (interfaceList.indexOf("vibrationsensor") >= 0) {
            page = "InputTriggerDevicePage.qml";
        } else if (interfaceList.indexOf("sensor") >= 0) {
            page = "SensorDevicePage.qml";
        } else if (interfaceList.indexOf("inputtrigger") >= 0) {
            page = "InputTriggerDevicePage.qml";
        } else if (interfaceList.indexOf("garagedoor") >= 0 ) {
            page = "GarageThingPage.qml";
        } else if (interfaceList.indexOf("light") >= 0) {
            page = "LightThingPage.qml";
        } else if (interfaceList.indexOf("shutter") >= 0  || interfaceList.indexOf("blind") >= 0) {
            page = "ShutterDevicePage.qml";
        } else if (interfaceList.indexOf("awning") >= 0) {
            page = "AwningThingPage.qml";
        } else if (interfaceList.indexOf("notifications") >= 0) {
            page = "NotificationsThingPage.qml";
        } else if (interfaceList.indexOf("fingerprintreader") >= 0) {
            page = "FingerprintReaderDevicePage.qml";
        } else if (interfaceList.indexOf("evcharger") >= 0) {
            page = "EvChargerThingPage.qml"
        } else if (interfaceList.indexOf("smartmeter") >= 0) {
            page = "SmartMeterDevicePage.qml"
        } else if (interfaceList.indexOf("powersocket") >= 0) {
            page = "PowersocketDevicePage.qml";
        } else if (interfaceList.indexOf("doorbell") >= 0) {
            page = "DoorbellDevicePage.qml";
        } else if (interfaceList.indexOf("irrigation") >= 0) {
            page = "IrrigationDevicePage.qml";
        } else if (interfaceList.indexOf("ventilation") >= 0) {
            page = "VentilationThingPage.qml";
        } else if (interfaceList.indexOf("barcodescanner") >= 0) {
            page = "BarcodeScannerThingPage.qml";
        } else if (interfaceList.indexOf("cleaningrobot") >= 0) {
            page = "CleaningRobotThingPage.qml";
        } else {
            page = "GenericThingPage.qml";
        }
        print("Selecting page", page, "for interface list:", interfaceList)
        return page;
    }

    function isDark(color) {
        var r, g, b;
        if (color.constructor.name === "Object") {
            r = color.r * 255;
            g = color.g * 255;
            b = color.b * 255;
        } else if (color.constructor.name === "String") {
            var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color);
            r = parseInt(result[1], 16)
            g = parseInt(result[2], 16)
            b = parseInt(result[3], 16)
        }

        return ((r * 299 + g * 587 + b * 114) / 1000) < 128
    }

    property var namedIcons: {
        "dashboard": "qrc:/icons/dashboard.svg",
        "group": "qrc:/icons/groups.svg",
        "folder": "qrc:/icons/folder.svg",
        "star": "qrc:/icons/starred.svg",
        "heart": "qrc:/icons/like.svg",
        "wrench": "qrc:/icons/configure.svg",
        "light": "qrc:/icons/light-on.svg",
        "sensor": "qrc:/icons/sensors.svg",
        "media": "qrc:/icons/media.svg",
        "powersocket": "qrc:/icons/powersocket.svg",
        "power": "qrc:/icons/system-shutdown.svg",
        "weather": "qrc:/icons/weather-app-symbolic.svg",
        "attention": "qrc:/icons/attention.svg",
        "shutter": "qrc:/icons/shutter/shutter-040.svg",
        "garage": "qrc:/icons/garage/garage-100.svg",
        "awning": "qrc:/icons/awning/awning-100.svg",
        "uncategorized": "qrc:/icons/select-none.svg",
        "closable": "qrc:/icons/closable-move.svg",
        "smartmeter": "qrc:/icons/smartmeter.svg",
        "heating": "qrc:/icons/thermostat/heating.svg",
        "cooling": "qrc:/icons/thermostat/cooling.svg",
        "meter": "qrc:/icons/dial.svg",
        "ev-charger": "qrc:/icons/ev-charger.svg",
        "battery": "qrc:/icons/battery/battery-100.svg",
        "message": "qrc:/icons/notification.svg",
        "irrigation": "qrc:/icons/irrigation.svg",
        "ventilation": "qrc:/icons/ventilation.svg",
        "lock": "qrc:/icons/smartlock.svg",
        "qrcode": "qrc:/icons/qrcode.svg",
        "cleaningrobot": "qrc:/icons/cleaning-robot.svg",
        "plant": "qrc:/icons/sensors/conductivity.svg",
        "water": "qrc:/icons/sensors/water.svg",
        "wind": "qrc:/icons/sensors/windspeed.svg",
        "cloud": "qrc:/icons/weathericons/weather-clouds.svg",
        "send": "qrc:/icons/send.svg",
    }
    function namedIcon(name) {
        if (!namedIcons.hasOwnProperty(name)) {
            console.error("No such named icon:", name)
            return
        }
        return namedIcons[name]
    }

    property ListModel scopesModel: ListModel {
        ListElement { text: qsTr("Admin"); scope: UserInfo.PermissionScopeAdmin; resetOnUnset: UserInfo.PermissionScopeNone }
        ListElement { text: qsTr("Control things"); scope: UserInfo.PermissionScopeControlThings; resetOnUnset: UserInfo.PermissionScopeNone }
        ListElement { text: qsTr("Configure things"); scope: UserInfo.PermissionScopeConfigureThings; resetOnUnset: UserInfo.PermissionScopeControlThings }
        ListElement { text: qsTr("Execute magic"); scope: UserInfo.PermissionScopeExecuteRules; resetOnUnset: UserInfo.PermissionScopeNone  }
        ListElement { text: qsTr("Configure magic"); scope: UserInfo.PermissionScopeConfigureRules; resetOnUnset: UserInfo.PermissionScopeExecuteRules }
    }

    function hasPermissionScope(permissions, requestedScope) {
        return (permissions & requestedScope) === requestedScope;
    }

    property bool inhibitChartsAnimation: PlatformHelper.deviceModel.startsWith("SM-G950") // Samsung S8 has a buggy GPU driver :(
    property int chartsAnimationOptions: !inhibitChartsAnimation ? ChartView.SeriesAnimations : ChartView.NoAnimation

    function generateColor(baseColor, index, alpha) {
        var stepSize = 30
        var baseHSV = rgb2hsv(baseColor.r, baseColor.g, baseColor.b)
        var currentHue = baseHSV[0]
        var handledColors = [currentHue]
        for (var i = 0; i < index; i++) {
            while (handledColors.indexOf(currentHue) >= 0) {
                currentHue = (currentHue + 60) % 360

                if (handledColors.indexOf(currentHue) >= 0) {
                    currentHue += /*60 + */stepSize
                    stepSize = Math.max(1, stepSize / 2)
                }
            }
            handledColors.push(currentHue)
        }
        return Qt.hsva(currentHue / 360, baseHSV[1], baseHSV[2], alpha || 1);
    }

    function rgb2hsv(r,g,b) {
      var v=Math.max(r,g,b), c=v-Math.min(r,g,b);
      var h= c && ((v==r) ? (g-b)/c : ((v==g) ? 2+(b-r)/c : 4+(r-g)/c));
      return [60*(h<0?h+6:h), v&&c/v, v];
    }

    readonly property var sensorInterfaceStateMap: {
        "temperaturesensor": "temperature",
        "humiditysensor": "humidity",
        "pressuresensor": "pressure",
        "moisturesensor": "moisture",
        "lightsensor": "lightIntensity",
        "conductivitysensor": "conductivity",
        "noisesensor": "noise",
        "cosensor": "co",
        "co2sensor": "co2",
        "gassensor": "gasLevel",
        "presencesensor": "isPresent",
        "daylightsensor": "daylight",
        "closablesensor": "closed",
        "watersensor": "waterDetected",
        "firesensor": "fireDetected",
        "waterlevelsensor": "waterLevel",
        "phsensor": "ph",
        "o2sensor": "o2saturation",
        "o3sensor": "o3",
        "orpsensor": "orp",
        "vocsensor": "voc",
        "cosensor": "co",
        "pm10sensor": "pm10",
        "pm25sensor": "pm25",
        "no2sensor": "no2"
    }

}
