/*
 * Copyright (C) 2012 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.
 */

#define LOG_TAG "InputDevice"

#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>

#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <ftl/enum.h>
#include <gui/constants.h>
#include <input/InputDevice.h>
#include <input/InputEventLabels.h>

using android::base::GetProperty;
using android::base::StringPrintf;

namespace android {

static const char* CONFIGURATION_FILE_DIR[] = {
        "idc/",
        "keylayout/",
        "keychars/",
};

static const char* CONFIGURATION_FILE_EXTENSION[] = {
        ".idc",
        ".kl",
        ".kcm",
};

static bool isValidNameChar(char ch) {
    return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_');
}

static void appendInputDeviceConfigurationFileRelativePath(std::string& path,
        const std::string& name, InputDeviceConfigurationFileType type) {
    path += CONFIGURATION_FILE_DIR[static_cast<int32_t>(type)];
    path += name;
    path += CONFIGURATION_FILE_EXTENSION[static_cast<int32_t>(type)];
}

std::string getInputDeviceConfigurationFilePathByDeviceIdentifier(
        const InputDeviceIdentifier& deviceIdentifier, InputDeviceConfigurationFileType type,
        const char* suffix) {
    if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
        if (deviceIdentifier.version != 0) {
            // Try vendor product version.
            std::string versionPath =
                    getInputDeviceConfigurationFilePathByName(StringPrintf("Vendor_%04x_Product_%"
                                                                           "04x_Version_%04x%s",
                                                                           deviceIdentifier.vendor,
                                                                           deviceIdentifier.product,
                                                                           deviceIdentifier.version,
                                                                           suffix),
                                                              type);
            if (!versionPath.empty()) {
                return versionPath;
            }
        }

        // Try vendor product.
        std::string productPath =
                getInputDeviceConfigurationFilePathByName(StringPrintf("Vendor_%04x_Product_%04x%s",
                                                                       deviceIdentifier.vendor,
                                                                       deviceIdentifier.product,
                                                                       suffix),
                                                          type);
        if (!productPath.empty()) {
            return productPath;
        }
    }

    // Try device name.
    return getInputDeviceConfigurationFilePathByName(deviceIdentifier.getCanonicalName() + suffix,
                                                     type);
}

std::string getInputDeviceConfigurationFilePathByName(
        const std::string& name, InputDeviceConfigurationFileType type) {
    // Search system repository.
    std::string path;

    // Treblized input device config files will be located /product/usr, /system_ext/usr,
    // /odm/usr or /vendor/usr.
    std::vector<std::string> pathPrefixes{
            "/product/usr/",
            "/system_ext/usr/",
            "/odm/usr/",
            "/vendor/usr/",
    };
    // These files may also be in the APEX pointed by input_device.config_file.apex sysprop.
    if (auto apex = GetProperty("input_device.config_file.apex", ""); !apex.empty()) {
        pathPrefixes.push_back("/apex/" + apex + "/etc/usr/");
    }
    // ANDROID_ROOT may not be set on host
    if (auto android_root = getenv("ANDROID_ROOT"); android_root != nullptr) {
        pathPrefixes.push_back(std::string(android_root) + "/usr/");
    }
    for (const auto& prefix : pathPrefixes) {
        path = prefix;
        appendInputDeviceConfigurationFileRelativePath(path, name, type);
#if DEBUG_PROBE
        ALOGD("Probing for system provided input device configuration file: path='%s'",
              path.c_str());
#endif
        if (!access(path.c_str(), R_OK)) {
#if DEBUG_PROBE
            ALOGD("Found");
#endif
            return path;
        }
    }

    // Search user repository.
    // TODO Should only look here if not in safe mode.
    path = "";
    char *androidData = getenv("ANDROID_DATA");
    if (androidData != nullptr) {
        path += androidData;
    }
    path += "/system/devices/";
    appendInputDeviceConfigurationFileRelativePath(path, name, type);
#if DEBUG_PROBE
    ALOGD("Probing for system user input device configuration file: path='%s'", path.c_str());
#endif
    if (!access(path.c_str(), R_OK)) {
#if DEBUG_PROBE
        ALOGD("Found");
#endif
        return path;
    }

    // Not found.
#if DEBUG_PROBE
    ALOGD("Probe failed to find input device configuration file: name='%s', type=%d",
            name.c_str(), type);
#endif
    return "";
}

// --- InputDeviceIdentifier

std::string InputDeviceIdentifier::getCanonicalName() const {
    std::string replacedName = name;
    for (char& ch : replacedName) {
        if (!isValidNameChar(ch)) {
            ch = '_';
        }
    }
    return replacedName;
}


// --- InputDeviceInfo ---

InputDeviceInfo::InputDeviceInfo() {
    initialize(-1, 0, -1, InputDeviceIdentifier(), "", false, false, ADISPLAY_ID_NONE);
}

InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other)
      : mId(other.mId),
        mGeneration(other.mGeneration),
        mControllerNumber(other.mControllerNumber),
        mIdentifier(other.mIdentifier),
        mAlias(other.mAlias),
        mIsExternal(other.mIsExternal),
        mHasMic(other.mHasMic),
        mKeyboardLayoutInfo(other.mKeyboardLayoutInfo),
        mSources(other.mSources),
        mKeyboardType(other.mKeyboardType),
        mKeyCharacterMap(other.mKeyCharacterMap),
        mUsiVersion(other.mUsiVersion),
        mAssociatedDisplayId(other.mAssociatedDisplayId),
        mHasVibrator(other.mHasVibrator),
        mHasBattery(other.mHasBattery),
        mHasButtonUnderPad(other.mHasButtonUnderPad),
        mHasSensor(other.mHasSensor),
        mMotionRanges(other.mMotionRanges),
        mSensors(other.mSensors),
        mLights(other.mLights),
        mViewBehavior(other.mViewBehavior) {}

InputDeviceInfo::~InputDeviceInfo() {
}

void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t controllerNumber,
                                 const InputDeviceIdentifier& identifier, const std::string& alias,
                                 bool isExternal, bool hasMic, int32_t associatedDisplayId,
                                 InputDeviceViewBehavior viewBehavior) {
    mId = id;
    mGeneration = generation;
    mControllerNumber = controllerNumber;
    mIdentifier = identifier;
    mAlias = alias;
    mIsExternal = isExternal;
    mHasMic = hasMic;
    mSources = 0;
    mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
    mAssociatedDisplayId = associatedDisplayId;
    mHasVibrator = false;
    mHasBattery = false;
    mHasButtonUnderPad = false;
    mHasSensor = false;
    mViewBehavior = viewBehavior;
    mUsiVersion.reset();
    mMotionRanges.clear();
    mSensors.clear();
    mLights.clear();
}

const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(
        int32_t axis, uint32_t source) const {
    for (const MotionRange& range : mMotionRanges) {
        if (range.axis == axis && isFromSource(range.source, source)) {
            return &range;
        }
    }
    return nullptr;
}

void InputDeviceInfo::addSource(uint32_t source) {
    mSources |= source;
}

void InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max,
        float flat, float fuzz, float resolution) {
    MotionRange range = { axis, source, min, max, flat, fuzz, resolution };
    mMotionRanges.push_back(range);
}

void InputDeviceInfo::addMotionRange(const MotionRange& range) {
    mMotionRanges.push_back(range);
}

void InputDeviceInfo::addSensorInfo(const InputDeviceSensorInfo& info) {
    if (mSensors.find(info.type) != mSensors.end()) {
        ALOGW("Sensor type %s already exists, will be replaced by new sensor added.",
              ftl::enum_string(info.type).c_str());
    }
    mSensors.insert_or_assign(info.type, info);
}

void InputDeviceInfo::addBatteryInfo(const InputDeviceBatteryInfo& info) {
    if (mBatteries.find(info.id) != mBatteries.end()) {
        ALOGW("Battery id %d already exists, will be replaced by new battery added.", info.id);
    }
    mBatteries.insert_or_assign(info.id, info);
}

void InputDeviceInfo::addLightInfo(const InputDeviceLightInfo& info) {
    if (mLights.find(info.id) != mLights.end()) {
        ALOGW("Light id %d already exists, will be replaced by new light added.", info.id);
    }
    mLights.insert_or_assign(info.id, info);
}

void InputDeviceInfo::setKeyboardType(int32_t keyboardType) {
    static_assert(AINPUT_KEYBOARD_TYPE_NONE < AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC);
    static_assert(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC < AINPUT_KEYBOARD_TYPE_ALPHABETIC);
    // There can be multiple subdevices with different keyboard types, set it to the highest type
    mKeyboardType = std::max(mKeyboardType, keyboardType);
}

void InputDeviceInfo::setKeyboardLayoutInfo(KeyboardLayoutInfo layoutInfo) {
    mKeyboardLayoutInfo = std::move(layoutInfo);
}

std::vector<InputDeviceSensorInfo> InputDeviceInfo::getSensors() {
    std::vector<InputDeviceSensorInfo> infos;
    infos.reserve(mSensors.size());
    for (const auto& [type, info] : mSensors) {
        infos.push_back(info);
    }
    return infos;
}

std::vector<InputDeviceLightInfo> InputDeviceInfo::getLights() {
    std::vector<InputDeviceLightInfo> infos;
    infos.reserve(mLights.size());
    for (const auto& [id, info] : mLights) {
        infos.push_back(info);
    }
    return infos;
}

} // namespace android
