package info.knacki.prometheusandroidexporter.collector;

import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;

import java.util.ArrayDeque;
import java.util.Collection;

import info.knacki.prometheusandroidexporter.CollectorType;
import info.knacki.prometheusandroidexporter.CollectorType.CollectorValue;
import info.knacki.prometheusandroidexporter.ICollector;

public class PowerCollector implements ICollector {
    private final CollectorType batteryLevelCollector = new CollectorType("battery_level", "Battery level", CollectorType.Type.GAUGE);
    private final CollectorType batteryTemperatureCollector = new CollectorType("battery_temp", "Battery temperature", CollectorType.Type.GAUGE);
    private final CollectorType batteryVoltageCollector = new CollectorType("battery_voltage", "Battery voltage (mV)", CollectorType.Type.GAUGE);

    private double GetBatteryLevel(Intent batteryStatus) {
        double batteryMax = batteryStatus != null ? batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, 0) : 0;
        double batteryLevel = batteryStatus != null ? batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) : -1;
        if (batteryMax == 0 || batteryLevel == -1)
            return -1;

        return (100.*batteryLevel) / batteryMax;
    }

    private String GetBatteryStatus(Intent batteryStatus) {
        int status = batteryStatus == null ? -1 : batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
        if (status == -1)
            return "Error";
        if (status == BatteryManager.BATTERY_STATUS_CHARGING)
            return "Charging";
        if (status == BatteryManager.BATTERY_STATUS_DISCHARGING)
            return "Discharging";
        if (status == BatteryManager.BATTERY_STATUS_FULL)
            return "Full";
        if (status == BatteryManager.BATTERY_STATUS_NOT_CHARGING)
            return "Not charging";
        return "Unknown";
    }

    private String GetBatteryPlugged(Intent batteryPlugged) {
        int status = batteryPlugged == null ? -1 : batteryPlugged.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
        if (status == -1)
            return "Error";
        if (status == BatteryManager.BATTERY_PLUGGED_AC)
            return "AC";
        if (status == BatteryManager.BATTERY_PLUGGED_USB)
            return "USB";
        if (status == BatteryManager.BATTERY_PLUGGED_WIRELESS)
            return "Wireless";
        return "Unknown";
    }

    private String GetBatteryHealth(Intent batteryHealth) {
        int health = batteryHealth == null ? -1 : batteryHealth.getIntExtra(BatteryManager.EXTRA_HEALTH, -1);
        if (health == -1)
            return "Error";
        if (health == BatteryManager.BATTERY_HEALTH_GOOD)
            return "Good";
        if (health == BatteryManager.BATTERY_HEALTH_COLD)
            return "Cold";
        if (health == BatteryManager.BATTERY_HEALTH_DEAD)
            return "Dead";
        if (health == BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE)
            return "Over Voltage";
        if (health == BatteryManager.BATTERY_HEALTH_OVERHEAT)
            return "Over Heat";
        if (health == BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE)
            return "Failure";
        return "Unknown";
    }

    private CollectorValue BatteryLevel(Intent batteryStatus) {
        CollectorValue val = batteryLevelCollector.new CollectorValue();
        val.SetValue(GetBatteryLevel(batteryStatus));
        val.AddParameter("Status", GetBatteryStatus(batteryStatus));
        val.AddParameter("Plugged", GetBatteryPlugged(batteryStatus));
        val.AddParameter("Health", GetBatteryHealth(batteryStatus));
        return val;
    }

    private CollectorValue BatteryTemperature(Intent battery) {
        CollectorValue val = batteryTemperatureCollector.new CollectorValue();
        final int error = -100000;
        int value = battery == null ? error : battery.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, error);
        val.SetValue(value == error ? Double.NaN : ((double) value) / 10);
        return val;
    }

    private CollectorValue BatteryVoltage(Intent battery) {
        CollectorValue val = batteryVoltageCollector.new CollectorValue();
        final int error = -100000;
        int value = battery == null ? error : battery.getIntExtra(BatteryManager.EXTRA_VOLTAGE, error);
        val.SetValue(value == error ? Double.NaN : ((double) value) / 10);
        return val;
    }

    @Override
    public Collection<CollectorValue> ReadValues(Context ctx) {
        Intent batteryStatus = ctx.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
        ArrayDeque<CollectorValue> result = new ArrayDeque<>();
        result.add(BatteryLevel(batteryStatus));
        result.add(BatteryTemperature(batteryStatus));
        result.add(BatteryVoltage(batteryStatus));
        // TODO BatteryManager.computeChargeTimeRemaining Time before battery get fully charged, msec, API >= 28
        return result;
    }
}
