/*
 * Copyright (C) 2020 Jan-Michael Brummer <jan.brummer@tabos.org>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include <wtf/glib/ChassisType.h>

#include <mutex>
#include <optional>
#include <wtf/glib/GUniquePtr.h>

namespace WTF {

static std::optional<ChassisType> readMachineInfoChassisType()
{
    GUniqueOutPtr<char> buffer;
    GUniqueOutPtr<GError> error;
    if (!g_file_get_contents("/etc/machine-info", &buffer.outPtr(), nullptr, &error.outPtr())) {
        if (!g_error_matches(error.get(), G_FILE_ERROR, G_FILE_ERROR_NOENT))
            g_warning("Could not open /etc/machine-info: %s", error->message);
        return std::nullopt;
    }

    GUniquePtr<char*> split(g_strsplit(buffer.get(), "\n", -1));
    for (int i = 0; split.get()[i]; ++i) {
        if (g_str_has_prefix(split.get()[i], "CHASSIS=")) {
            char* chassis = split.get()[i] + 8;

            GUniquePtr<char> unquoted(g_shell_unquote(chassis, &error.outPtr()));
            if (error)
                g_warning("Could not unquote chassis type %s: %s", chassis, error->message);

            if (!strcmp(unquoted.get(), "tablet") || !strcmp(unquoted.get(), "handset"))
                return ChassisType::Mobile;

            return ChassisType::Desktop;
        }
    }

    return std::nullopt;
}

static std::optional<ChassisType> readDMIChassisType()
{
    GUniqueOutPtr<char> buffer;
    GUniqueOutPtr<GError> error;
    if (g_file_get_contents("/sys/class/dmi/id/chassis_type", &buffer.outPtr(), nullptr, &error.outPtr())) {
        int type = strtol(buffer.get(), nullptr, 10);

        // See the SMBIOS Specification 3.0 section 7.4.1 for details about the values listed here:
        // https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf
        switch (type) {
        case 0x3: /* Desktop */
        case 0x4: /* Low Profile Desktop */
        case 0x6: /* Mini Tower */
        case 0x7: /* Tower */
        case 0x8: /* Portable */
        case 0x9: /* Laptop */
        case 0xA: /* Notebook */
        case 0xE: /* Sub Notebook */
        case 0x11: /* Main Server Chassis */
        case 0x1C: /* Blade */
        case 0x1D: /* Blade Enclosure */
        case 0x1F: /* Convertible */
        case 0x20: /* Detachable */
            return ChassisType::Desktop;

        case 0xB: /* Hand Held */
        case 0x1E: /* Tablet */
            return ChassisType::Mobile;
        }
    } else if (!g_error_matches(error.get(), G_FILE_ERROR, G_FILE_ERROR_NOENT))
        g_warning("Could not open /sys/class/dmi/id/chassis_type: %s", error->message);

    return std::nullopt;
}

static std::optional<ChassisType> readACPIChassisType()
{
    GUniqueOutPtr<char> buffer;
    GUniqueOutPtr<GError> error;
    if (g_file_get_contents("/sys/firmware/acpi/pm_profile", &buffer.outPtr(), nullptr, &error.outPtr())) {
        int type = strtol(buffer.get(), nullptr, 10);

        // See the ACPI 5.0 Spec Section 5.2.9.1 for details:
        // http://www.acpi.info/DOWNLOADS/ACPIspec50.pdf
        switch (type) {
        case 1: /* Desktop */
        case 2: /* Mobile */
        case 3: /* Workstation */
        case 4: /* Enterprise Server */
        case 5: /* SOHO Server */
        case 6: /* Appliance PC */
        case 7: /* Performance Server */
            return ChassisType::Desktop;

        case 8: /* Tablet */
            return ChassisType::Mobile;
        }
    } else if (!g_error_matches(error.get(), G_FILE_ERROR, G_FILE_ERROR_NOENT))
        g_warning("Could not open /sys/firmware/acpi/pm_profile: %s", error->message);

    return std::nullopt;
}

ChassisType chassisType()
{
    static ChassisType chassisType;
    static std::once_flag initializeChassis;
    std::call_once(initializeChassis, [] {
        auto optionalChassisType = readMachineInfoChassisType();
        if (!optionalChassisType)
            optionalChassisType = readDMIChassisType();
        if (!optionalChassisType)
            optionalChassisType = readACPIChassisType();
        chassisType = optionalChassisType.value_or(ChassisType::Desktop);
    });

    return chassisType;
}

} // namespace WTF
