/*
 * Copyright (C) 2021 The Android Open Source 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.
 */
#pragma once

#include <algorithm>
#include <cmath>

#include "HardwareBase.h"
#include "Vibrator.h"

#define PROC_SND_PCM "/proc/asound/pcm"
#define HAPTIC_PCM_DEVICE_SYMBOL "haptic nohost playback"

static struct pcm_config haptic_nohost_config = {
        .channels = 1,
        .rate = 48000,
        .period_size = 80,
        .period_count = 2,
        .format = PCM_FORMAT_S16_LE,
};

enum WaveformIndex : uint16_t {
    /* Physical waveform */
    WAVEFORM_LONG_VIBRATION_EFFECT_INDEX = 0,
    WAVEFORM_RESERVED_INDEX_1 = 1,
    WAVEFORM_CLICK_INDEX = 2,
    WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX = 3,
    WAVEFORM_THUD_INDEX = 4,
    WAVEFORM_SPIN_INDEX = 5,
    WAVEFORM_QUICK_RISE_INDEX = 6,
    WAVEFORM_SLOW_RISE_INDEX = 7,
    WAVEFORM_QUICK_FALL_INDEX = 8,
    WAVEFORM_LIGHT_TICK_INDEX = 9,
    WAVEFORM_LOW_TICK_INDEX = 10,
    WAVEFORM_RESERVED_MFG_1,
    WAVEFORM_RESERVED_MFG_2,
    WAVEFORM_RESERVED_MFG_3,
    WAVEFORM_MAX_PHYSICAL_INDEX,
    /* OWT waveform */
    WAVEFORM_COMPOSE = WAVEFORM_MAX_PHYSICAL_INDEX,
    WAVEFORM_PWLE,
    /*
     * Refer to <linux/input.h>, the WAVEFORM_MAX_INDEX must not exceed 96.
     * #define FF_GAIN          0x60  // 96 in decimal
     * #define FF_MAX_EFFECTS   FF_GAIN
     */
    WAVEFORM_MAX_INDEX,
};

namespace aidl {
namespace android {
namespace hardware {
namespace vibrator {

class HwApi : public Vibrator::HwApi, private HwApiBase {
  public:
    static std::unique_ptr<HwApi> Create() {
        auto hwapi = std::unique_ptr<HwApi>(new HwApi());
        return hwapi;
    }
    HwApi() {
        open("calibration/f0_stored", &mF0);
        open("default/f0_offset", &mF0Offset);
        open("calibration/redc_stored", &mRedc);
        open("calibration/q_stored", &mQ);
        open("default/vibe_state", &mVibeState);
        open("default/num_waves", &mEffectCount);
        open("default/owt_free_space", &mOwtFreeSpace);
        open("default/f0_comp_enable", &mF0CompEnable);
        open("default/redc_comp_enable", &mRedcCompEnable);
        open("default/delay_before_stop_playback_us", &mMinOnOffInterval);
    }

    bool setF0(std::string value) override { return set(value, &mF0); }
    bool setF0Offset(uint32_t value) override { return set(value, &mF0Offset); }
    bool setRedc(std::string value) override { return set(value, &mRedc); }
    bool setQ(std::string value) override { return set(value, &mQ); }
    bool getEffectCount(uint32_t *value) override { return get(value, &mEffectCount); }
    bool pollVibeState(uint32_t value, int32_t timeoutMs) override {
        return poll(value, &mVibeState, timeoutMs);
    }
    bool hasOwtFreeSpace() override { return has(mOwtFreeSpace); }
    bool getOwtFreeSpace(uint32_t *value) override { return get(value, &mOwtFreeSpace); }
    bool setF0CompEnable(bool value) override { return set(value, &mF0CompEnable); }
    bool setRedcCompEnable(bool value) override { return set(value, &mRedcCompEnable); }
    bool setMinOnOffInterval(uint32_t value) override { return set(value, &mMinOnOffInterval); }
    // TODO(b/234338136): Need to add the force feedback HW API test cases
    bool setFFGain(int fd, uint16_t value) override {
        struct input_event gain = {
                .type = EV_FF,
                .code = FF_GAIN,
                .value = value,
        };
        if (write(fd, (const void *)&gain, sizeof(gain)) != sizeof(gain)) {
            return false;
        }
        return true;
    }
    bool setFFEffect(int fd, struct ff_effect *effect, uint16_t timeoutMs) override {
        if (ioctl(fd, EVIOCSFF, effect) < 0) {
            ALOGE("setFFEffect fail");
            return false;
        } else {
            return true;
        }
    }
    bool setFFPlay(int fd, int8_t index, bool value) override {
        struct input_event play = {
                .type = EV_FF,
                .code = static_cast<uint16_t>(index),
                .value = value,
        };
        if (write(fd, (const void *)&play, sizeof(play)) != sizeof(play)) {
            return false;
        } else {
            return true;
        }
    }
    bool getHapticAlsaDevice(int *card, int *device) override {
        std::string line;
        std::ifstream myfile(PROC_SND_PCM);
        if (myfile.is_open()) {
            while (getline(myfile, line)) {
                if (line.find(HAPTIC_PCM_DEVICE_SYMBOL) != std::string::npos) {
                    std::stringstream ss(line);
                    std::string currentToken;
                    std::getline(ss, currentToken, ':');
                    sscanf(currentToken.c_str(), "%d-%d", card, device);
                    return true;
                }
            }
            myfile.close();
        } else {
            ALOGE("Failed to read file: %s", PROC_SND_PCM);
        }
        return false;
    }
    bool setHapticPcmAmp(struct pcm **haptic_pcm, bool enable, int card, int device) override {
        int ret = 0;

        if (enable) {
            *haptic_pcm = pcm_open(card, device, PCM_OUT, &haptic_nohost_config);
            if (!pcm_is_ready(*haptic_pcm)) {
                ALOGE("cannot open pcm_out driver: %s", pcm_get_error(*haptic_pcm));
                goto fail;
            }

            ret = pcm_prepare(*haptic_pcm);
            if (ret < 0) {
                ALOGE("cannot prepare haptic_pcm: %s", pcm_get_error(*haptic_pcm));
                goto fail;
            }

            ret = pcm_start(*haptic_pcm);
            if (ret < 0) {
                ALOGE("cannot start haptic_pcm: %s", pcm_get_error(*haptic_pcm));
                goto fail;
            }

            return true;
        } else {
            if (*haptic_pcm) {
                pcm_close(*haptic_pcm);
                *haptic_pcm = NULL;
            }
            return true;
        }

    fail:
        pcm_close(*haptic_pcm);
        *haptic_pcm = NULL;
        return false;
    }
    bool uploadOwtEffect(int fd, uint8_t *owtData, uint32_t numBytes, struct ff_effect *effect,
                         uint32_t *outEffectIndex, int *status) override {
        (*effect).u.periodic.custom_len = numBytes / sizeof(uint16_t);
        delete[] ((*effect).u.periodic.custom_data);
        (*effect).u.periodic.custom_data = new int16_t[(*effect).u.periodic.custom_len]{0x0000};
        if ((*effect).u.periodic.custom_data == nullptr) {
            ALOGE("Failed to allocate memory for custom data\n");
            *status = EX_NULL_POINTER;
            return false;
        }
        memcpy((*effect).u.periodic.custom_data, owtData, numBytes);

        if ((*effect).id != -1) {
            ALOGE("(*effect).id != -1");
        }

        /* Create a new OWT waveform to update the PWLE or composite effect. */
        (*effect).id = -1;
        if (ioctl(fd, EVIOCSFF, effect) < 0) {
            ALOGE("Failed to upload effect %d (%d): %s", *outEffectIndex, errno, strerror(errno));
            delete[] ((*effect).u.periodic.custom_data);
            *status = EX_ILLEGAL_STATE;
            return false;
        }

        if ((*effect).id >= FF_MAX_EFFECTS || (*effect).id < 0) {
            ALOGE("Invalid waveform index after upload OWT effect: %d", (*effect).id);
            *status = EX_ILLEGAL_ARGUMENT;
            return false;
        }
        *outEffectIndex = (*effect).id;
        *status = 0;
        return true;
    }
    bool eraseOwtEffect(int fd, int8_t effectIndex, std::vector<ff_effect> *effect) override {
        uint32_t effectCountBefore, effectCountAfter, i, successFlush = 0;

        if (effectIndex < WAVEFORM_MAX_PHYSICAL_INDEX) {
            ALOGE("Invalid waveform index for OWT erase: %d", effectIndex);
            return false;
        }
        // Turn off the waiting time for SVC init phase to complete since chip
        // should already under STOP state
        setMinOnOffInterval(0);
        // Do erase flow
        if (effectIndex < WAVEFORM_MAX_INDEX) {
            /* Normal situation. Only erase the effect which we just played. */
            if (ioctl(fd, EVIOCRMFF, effectIndex) < 0) {
                ALOGE("Failed to erase effect %d (%d): %s", effectIndex, errno, strerror(errno));
            }
            for (i = WAVEFORM_MAX_PHYSICAL_INDEX; i < WAVEFORM_MAX_INDEX; i++) {
                if ((*effect)[i].id == effectIndex) {
                    (*effect)[i].id = -1;
                    break;
                }
            }
        } else {
            /* Flush all non-prestored effects of ff-core and driver. */
            getEffectCount(&effectCountBefore);
            for (i = WAVEFORM_MAX_PHYSICAL_INDEX; i < FF_MAX_EFFECTS; i++) {
                if (ioctl(fd, EVIOCRMFF, i) >= 0) {
                    successFlush++;
                }
            }
            getEffectCount(&effectCountAfter);
            ALOGW("Flushed effects: ff: %d; driver: %d -> %d; success: %d", effectIndex,
                  effectCountBefore, effectCountAfter, successFlush);
            /* Reset all OWT effect index of HAL. */
            for (i = WAVEFORM_MAX_PHYSICAL_INDEX; i < WAVEFORM_MAX_INDEX; i++) {
                (*effect)[i].id = -1;
            }
        }
        // Turn on the waiting time for SVC init phase to complete
        setMinOnOffInterval(Vibrator::MIN_ON_OFF_INTERVAL_US);
        return true;
    }

    void debug(int fd) override { HwApiBase::debug(fd); }

  private:
    std::ofstream mF0;
    std::ofstream mF0Offset;
    std::ofstream mRedc;
    std::ofstream mQ;
    std::ifstream mEffectCount;
    std::ifstream mVibeState;
    std::ifstream mOwtFreeSpace;
    std::ofstream mF0CompEnable;
    std::ofstream mRedcCompEnable;
    std::ofstream mMinOnOffInterval;
};

class HwCal : public Vibrator::HwCal, private HwCalBase {
  private:
    static constexpr char VERSION[] = "version";
    static constexpr char F0_CONFIG[] = "f0_measured";
    static constexpr char F0_CONFIG_DUAL[] = "f0_measured_dual";
    static constexpr char REDC_CONFIG[] = "redc_measured";
    static constexpr char Q_CONFIG[] = "q_measured";
    static constexpr char TICK_VOLTAGES_CONFIG[] = "v_tick";
    static constexpr char CLICK_VOLTAGES_CONFIG[] = "v_click";
    static constexpr char LONG_VOLTAGES_CONFIG[] = "v_long";

    static constexpr uint32_t VERSION_DEFAULT = 2;
    static constexpr int32_t DEFAULT_FREQUENCY_SHIFT = 0;
    static constexpr std::array<uint32_t, 2> V_TICK_DEFAULT = {1, 100};
    static constexpr std::array<uint32_t, 2> V_CLICK_DEFAULT = {1, 100};
    static constexpr std::array<uint32_t, 2> V_LONG_DEFAULT = {1, 100};

  public:
    HwCal() {}
    static std::unique_ptr<HwCal> Create() {
        auto hwcal = std::unique_ptr<HwCal>(new HwCal());
        return hwcal;
    }

    bool getVersion(uint32_t *value) override {
        if (getPersist(VERSION, value)) {
            return true;
        }
        *value = VERSION_DEFAULT;
        return true;
    }
    bool getLongFrequencyShift(int32_t *value) override {
        return getProperty("long.frequency.shift", value, DEFAULT_FREQUENCY_SHIFT);
    }
    bool getF0(std::string *value) override { return getPersist(F0_CONFIG, value); }
    bool getF0SyncOffset(uint32_t *value) override {
        std::string cal_0{8, '0'};
        std::string cal_1{8, '0'};

        if (getPersist(F0_CONFIG, &cal_0) && getPersist(F0_CONFIG_DUAL, &cal_1)) {
            float f0_0 = static_cast<float>(std::stoul(cal_0, nullptr, 16)) / (1 << 14);
            float f0_1 = static_cast<float>(std::stoul(cal_1, nullptr, 16)) / (1 << 14);
            float f0_offset = std::abs(f0_0 - f0_1)/2;

            if (f0_0 < f0_1) {
                *value = static_cast<uint32_t>(f0_offset * std::pow(2, 14));
            } else if (f0_0 > f0_1) {
                *value = static_cast<uint32_t>(std::pow(2, 24) - std::abs(f0_offset) * std::pow(2, 14));
            } else {
                *value = 0;
            }

            return true;
        } else {
            ALOGE("Vibrator: Unable to load F0_CONFIG or F0_CONFIG_DUAL config");
            *value = 0;
            return false;
        }
    }
    bool getRedc(std::string *value) override { return getPersist(REDC_CONFIG, value); }
    bool getQ(std::string *value) override { return getPersist(Q_CONFIG, value); }
    bool getTickVolLevels(std::array<uint32_t, 2> *value) override {
        if (getPersist(TICK_VOLTAGES_CONFIG, value)) {
            return true;
        }
        *value = V_TICK_DEFAULT;
        return true;
    }
    bool getClickVolLevels(std::array<uint32_t, 2> *value) override {
        if (getPersist(CLICK_VOLTAGES_CONFIG, value)) {
            return true;
        }
        *value = V_CLICK_DEFAULT;
        return true;
    }
    bool getLongVolLevels(std::array<uint32_t, 2> *value) override {
        if (getPersist(LONG_VOLTAGES_CONFIG, value)) {
            return true;
        }
        *value = V_LONG_DEFAULT;
        return true;
    }
    bool isChirpEnabled() override {
        return utils::getProperty("persist.vendor.vibrator.hal.chirp.enabled", false);
    }
    bool getSupportedPrimitives(uint32_t *value) override {
        return getProperty("supported_primitives", value, (uint32_t)0);
    }
    bool isF0CompEnabled() override {
        bool value;
        getProperty("f0.comp.enabled", &value, true);
        return value;
    }
    bool isRedcCompEnabled() override {
        bool value;
        getProperty("redc.comp.enabled", &value, false);
        return value;
    }
    void debug(int fd) override { HwCalBase::debug(fd); }
};

}  // namespace vibrator
}  // namespace hardware
}  // namespace android
}  // namespace aidl
