/*
 * Copyright (C) 2020 The LineageOS Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "android.hardware.power@1.0-service.exynos"

#include "Power.h"
#include <android-base/logging.h>
#include <filesystem>
#include <fstream>
#include <iostream>
#include "samsung_lights.h"
#include "samsung_power.h"

namespace android {
namespace hardware {
namespace power {
namespace V1_0 {
namespace implementation {

/*
 * Write value to path and close file.
 */
template <typename T>
static void set(const std::string& path, const T& value) {
    std::ofstream file(path);
    file << value << std::endl;
}

template <typename T>
static T get(const std::string& path, const T& def) {
    std::ifstream file(path);
    T result;

    file >> result;
    return file.fail() ? def : result;
}

Return<void> Power::setInteractive(bool interactive) {
    if (!initialized) {
        initialize();
    }

    if (!interactive) {
        int32_t panel_brightness = get(PANEL_BRIGHTNESS_NODE, -1);

        if (panel_brightness > 0) {
            LOG(VERBOSE) << "Moving to non-interactive state, but screen is still on,"
                         << "not disabling input devices";
            goto out;
        }
    }

    if (!sec_touchscreen.empty()) {
        set(sec_touchscreen, interactive ? "1" : "0");
    }

    if (!sec_touchkey.empty()) {
        if (!interactive) {
            int button_state = get(sec_touchkey, -1);

            if (button_state < 0) {
                LOG(ERROR) << "Failed to read touchkey state";
                goto out;
            }

            /*
             * If button_state is 0, the keys have been disabled by another component
             * (for example lineagehw), which means we don't want them to be enabled when resuming
             * from suspend.
             */
            if (button_state == 0) {
                touchkeys_blocked = true;
            }
        }

        if (!touchkeys_blocked) {
            set(sec_touchkey, interactive ? "1" : "0");
        }
    }

out:
    for (const std::string& interactivePath : cpuInteractivePaths) {
        set(interactivePath + "/io_is_busy", interactive ? "1" : "0");
    }

    return Void();
}

Return<void> Power::powerHint(PowerHint hint, int32_t data) {
    if (!initialized) {
        initialize();
    }

    /* Bail out if low-power mode is active */
    if (current_profile == PowerProfile::POWER_SAVE && hint != PowerHint::LOW_POWER &&
        hint != static_cast<PowerHint>(LineagePowerHint::SET_PROFILE)) {
        LOG(VERBOSE) << "PROFILE_POWER_SAVE active, ignoring hint " << static_cast<int32_t>(hint);
        return Void();
    }

    switch (hint) {
        case PowerHint::INTERACTION:
        case PowerHint::LAUNCH:
            sendBoostpulse();
            break;
        case PowerHint::LOW_POWER:
            setProfile(data ? PowerProfile::POWER_SAVE : PowerProfile::BALANCED);
            break;
        default:
            if (hint == static_cast<PowerHint>(LineagePowerHint::SET_PROFILE)) {
                setProfile(static_cast<PowerProfile>(data));
            } else if (hint == static_cast<PowerHint>(LineagePowerHint::CPU_BOOST)) {
                sendBoost(data);
            } else {
                LOG(INFO) << "Unknown power hint: " << static_cast<int32_t>(hint);
            }
            break;
    }
    return Void();
}

Return<void> Power::setFeature(Feature feature __unused, bool activate __unused) {
    if (!initialized) {
        initialize();
    }

#ifdef TAP_TO_WAKE_NODE
    if (feature == Feature::POWER_FEATURE_DOUBLE_TAP_TO_WAKE) {
        set(TAP_TO_WAKE_NODE, activate ? "1" : "0");
    }
#endif

    return Void();
}

Return<void> Power::getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb) {
    _hidl_cb({}, Status::SUCCESS);
    return Void();
}

Return<int32_t> Power::getFeature(LineageFeature feature) {
    switch (feature) {
        case LineageFeature::SUPPORTED_PROFILES:
            return static_cast<int32_t>(PowerProfile::MAX);
        default:
            return -1;
    }
}

void Power::initialize() {
    findInputNodes();

    current_profile = PowerProfile::BALANCED;

    for (const std::string& interactivePath : cpuInteractivePaths) {
        hispeed_freqs.emplace_back(get<std::string>(interactivePath + "/hispeed_freq", ""));
    }

    for (const std::string& sysfsPath : cpuSysfsPaths) {
        max_freqs.emplace_back(get<std::string>(sysfsPath + "/cpufreq/scaling_max_freq", ""));
    }

    initialized = true;
}

void Power::findInputNodes() {
    std::error_code ec;
    for (auto& de : std::filesystem::directory_iterator("/sys/class/input/", ec)) {
        /* we are only interested in the input devices that we can access */
        if (ec || de.path().string().find("/sys/class/input/input") == std::string::npos) {
            continue;
        }

        for (auto& de2 : std::filesystem::directory_iterator(de.path(), ec)) {
            if (!ec && de2.path().string().find("/name") != std::string::npos) {
                std::string content = get<std::string>(de2.path(), "");
                if (content == "sec_touchkey") {
                    sec_touchkey = de.path().string().append("/enabled");
                    LOG(INFO) << "found sec_touchkey: " << sec_touchkey;
                } else if (content == "sec_touchscreen") {
                    sec_touchscreen = de.path().string().append("/enabled");
                    LOG(INFO) << "found sec_touchscreen: " << sec_touchscreen;
                }
            }
        }
    }
}

void Power::setProfile(PowerProfile profile) {
    if (current_profile == profile) {
        return;
    }

    switch (profile) {
        case PowerProfile::POWER_SAVE:
            // Limit to hispeed freq
            for (int i = 0; i < cpuSysfsPaths.size(); i++) {
                if (hispeed_freqs.size() > i && !hispeed_freqs.at(i).empty()) {
                    set(cpuSysfsPaths.at(i) + "/cpufreq/scaling_max_freq", hispeed_freqs.at(i));
                }
            }
            break;
        case PowerProfile::BALANCED:
        case PowerProfile::HIGH_PERFORMANCE:
            // Restore normal max freq
            for (int i = 0; i < cpuSysfsPaths.size(); i++) {
                if (max_freqs.size() > i && !max_freqs.at(i).empty()) {
                    set(cpuSysfsPaths.at(i) + "/cpufreq/scaling_max_freq", max_freqs.at(i));
                }
            }
            break;
        default:
            break;
    }
}

void Power::sendBoostpulse() {
    // the boostpulse node is only valid for the LITTLE cluster
    set(cpuInteractivePaths.front() + "/boostpulse", "1");
}

void Power::sendBoost(int duration_us) {
    set(cpuInteractivePaths.front() + "/boost", "1");

    usleep(duration_us);

    set(cpuInteractivePaths.front() + "/boost", "0");
}

}  // namespace implementation
}  // namespace V1_0
}  // namespace power
}  // namespace hardware
}  // namespace android
