/*
 * Copyright 2022 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.
 */

#include "InputMapperTest.h"

#include <InputReaderBase.h>
#include <gtest/gtest.h>
#include <ui/Rotation.h>
#include <utils/Timers.h>

#include "NotifyArgs.h"

namespace android {

using testing::_;
using testing::NiceMock;
using testing::Return;
using testing::ReturnRef;

void InputMapperUnitTest::SetUpWithBus(int bus) {
    mFakePolicy = sp<FakeInputReaderPolicy>::make();

    EXPECT_CALL(mMockInputReaderContext, getPolicy()).WillRepeatedly(Return(mFakePolicy.get()));

    EXPECT_CALL(mMockInputReaderContext, getEventHub()).WillRepeatedly(Return(&mMockEventHub));

    mIdentifier.name = "device";
    mIdentifier.location = "USB1";
    mIdentifier.bus = bus;
    EXPECT_CALL(mMockEventHub, getDeviceIdentifier(EVENTHUB_ID))
            .WillRepeatedly(Return(mIdentifier));
    EXPECT_CALL(mMockEventHub, getConfiguration(EVENTHUB_ID)).WillRepeatedly([&](int32_t) {
        return mPropertyMap;
    });

    mDevice = std::make_unique<NiceMock<MockInputDevice>>(&mMockInputReaderContext, DEVICE_ID,
                                                          /*generation=*/2, mIdentifier);
    ON_CALL((*mDevice), getConfiguration).WillByDefault(ReturnRef(mPropertyMap));
    mDeviceContext = std::make_unique<InputDeviceContext>(*mDevice, EVENTHUB_ID);
}

void InputMapperUnitTest::setupAxis(int axis, bool valid, int32_t min, int32_t max,
                                    int32_t resolution, int32_t flat, int32_t fuzz) {
    EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis))
            .WillRepeatedly(Return(valid ? std::optional<RawAbsoluteAxisInfo>{{
                                                   .minValue = min,
                                                   .maxValue = max,
                                                   .flat = flat,
                                                   .fuzz = fuzz,
                                                   .resolution = resolution,
                                           }}
                                         : std::nullopt));
}

void InputMapperUnitTest::expectScanCodes(bool present, std::set<int> scanCodes) {
    for (const auto& scanCode : scanCodes) {
        EXPECT_CALL(mMockEventHub, hasScanCode(EVENTHUB_ID, scanCode))
                .WillRepeatedly(testing::Return(present));
    }
}

void InputMapperUnitTest::setScanCodeState(KeyState state, std::set<int> scanCodes) {
    for (const auto& scanCode : scanCodes) {
        EXPECT_CALL(mMockEventHub, getScanCodeState(EVENTHUB_ID, scanCode))
                .WillRepeatedly(testing::Return(static_cast<int>(state)));
    }
}

void InputMapperUnitTest::setKeyCodeState(KeyState state, std::set<int> keyCodes) {
    for (const auto& keyCode : keyCodes) {
        EXPECT_CALL(mMockEventHub, getKeyCodeState(EVENTHUB_ID, keyCode))
                .WillRepeatedly(testing::Return(static_cast<int>(state)));
    }
}

void InputMapperUnitTest::setSwitchState(int32_t state, std::set<int32_t> switchCodes) {
    for (const auto& switchCode : switchCodes) {
        EXPECT_CALL(mMockEventHub, getSwitchState(EVENTHUB_ID, switchCode))
                .WillRepeatedly(testing::Return(static_cast<int>(state)));
    }
}

std::list<NotifyArgs> InputMapperUnitTest::process(int32_t type, int32_t code, int32_t value) {
    nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
    return process(when, type, code, value);
}

std::list<NotifyArgs> InputMapperUnitTest::process(nsecs_t when, int32_t type, int32_t code,
                                                   int32_t value) {
    return process(when, when, type, code, value);
}

std::list<NotifyArgs> InputMapperUnitTest::process(nsecs_t when, nsecs_t readTime, int32_t type,
                                                   int32_t code, int32_t value) {
    RawEvent event;
    event.when = when;
    event.readTime = readTime;
    event.deviceId = mMapper->getDeviceContext().getEventHubId();
    event.type = type;
    event.code = code;
    event.value = value;
    return mMapper->process(event);
}

const char* InputMapperTest::DEVICE_NAME = "device";
const char* InputMapperTest::DEVICE_LOCATION = "USB1";
const ftl::Flags<InputDeviceClass> InputMapperTest::DEVICE_CLASSES =
        ftl::Flags<InputDeviceClass>(0); // not needed for current tests

void InputMapperTest::SetUp(ftl::Flags<InputDeviceClass> classes, int bus) {
    mFakeEventHub = std::make_unique<FakeEventHub>();
    mFakePolicy = sp<FakeInputReaderPolicy>::make();
    mFakeListener = std::make_unique<TestInputListener>();
    mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy, *mFakeListener);
    mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes, bus);
    // Consume the device reset notification generated when adding a new device.
    mFakeListener->assertNotifyDeviceResetWasCalled();
}

void InputMapperTest::SetUp() {
    SetUp(DEVICE_CLASSES);
}

void InputMapperTest::TearDown() {
    mFakeListener.reset();
    mFakePolicy.clear();
}

void InputMapperTest::addConfigurationProperty(const char* key, const char* value) {
    mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, key, value);
}

std::list<NotifyArgs> InputMapperTest::configureDevice(ConfigurationChanges changes) {
    using namespace ftl::flag_operators;
    if (!changes.any() ||
        (changes.any(InputReaderConfiguration::Change::DISPLAY_INFO |
                     InputReaderConfiguration::Change::POINTER_CAPTURE |
                     InputReaderConfiguration::Change::DEVICE_TYPE))) {
        mReader->requestRefreshConfiguration(changes);
        mReader->loopOnce();
    }
    std::list<NotifyArgs> out =
            mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), changes);
    // Loop the reader to flush the input listener queue.
    for (const NotifyArgs& args : out) {
        mFakeListener->notify(args);
    }
    mReader->loopOnce();
    return out;
}

std::shared_ptr<InputDevice> InputMapperTest::newDevice(int32_t deviceId, const std::string& name,
                                                        const std::string& location,
                                                        int32_t eventHubId,
                                                        ftl::Flags<InputDeviceClass> classes,
                                                        int bus) {
    InputDeviceIdentifier identifier;
    identifier.name = name;
    identifier.location = location;
    identifier.bus = bus;
    std::shared_ptr<InputDevice> device =
            std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
                                          identifier);
    mReader->pushNextDevice(device);
    mFakeEventHub->addDevice(eventHubId, name, classes, bus);
    mReader->loopOnce();
    return device;
}

void InputMapperTest::setDisplayInfoAndReconfigure(ui::LogicalDisplayId displayId, int32_t width,
                                                   int32_t height, ui::Rotation orientation,
                                                   const std::string& uniqueId,
                                                   std::optional<uint8_t> physicalPort,
                                                   ViewportType viewportType) {
    mFakePolicy->addDisplayViewport(displayId, width, height, orientation, /* isActive= */ true,
                                    uniqueId, physicalPort, viewportType);
    configureDevice(InputReaderConfiguration::Change::DISPLAY_INFO);
}

void InputMapperTest::clearViewports() {
    mFakePolicy->clearViewports();
}

std::list<NotifyArgs> InputMapperTest::process(InputMapper& mapper, nsecs_t when, nsecs_t readTime,
                                               int32_t type, int32_t code, int32_t value) {
    RawEvent event;
    event.when = when;
    event.readTime = readTime;
    event.deviceId = mapper.getDeviceContext().getEventHubId();
    event.type = type;
    event.code = code;
    event.value = value;
    std::list<NotifyArgs> processArgList = mapper.process(event);
    for (const NotifyArgs& args : processArgList) {
        mFakeListener->notify(args);
    }
    // Loop the reader to flush the input listener queue.
    mReader->loopOnce();
    return processArgList;
}

void InputMapperTest::resetMapper(InputMapper& mapper, nsecs_t when) {
    const auto resetArgs = mapper.reset(when);
    for (const auto args : resetArgs) {
        mFakeListener->notify(args);
    }
    // Loop the reader to flush the input listener queue.
    mReader->loopOnce();
}

std::list<NotifyArgs> InputMapperTest::handleTimeout(InputMapper& mapper, nsecs_t when) {
    std::list<NotifyArgs> generatedArgs = mapper.timeoutExpired(when);
    for (const NotifyArgs& args : generatedArgs) {
        mFakeListener->notify(args);
    }
    // Loop the reader to flush the input listener queue.
    mReader->loopOnce();
    return generatedArgs;
}

void assertMotionRange(const InputDeviceInfo& info, int32_t axis, uint32_t source, float min,
                       float max, float flat, float fuzz) {
    const InputDeviceInfo::MotionRange* range = info.getMotionRange(axis, source);
    ASSERT_TRUE(range != nullptr) << "Axis: " << axis << " Source: " << source;
    ASSERT_EQ(axis, range->axis) << "Axis: " << axis << " Source: " << source;
    ASSERT_EQ(source, range->source) << "Axis: " << axis << " Source: " << source;
    ASSERT_NEAR(min, range->min, EPSILON) << "Axis: " << axis << " Source: " << source;
    ASSERT_NEAR(max, range->max, EPSILON) << "Axis: " << axis << " Source: " << source;
    ASSERT_NEAR(flat, range->flat, EPSILON) << "Axis: " << axis << " Source: " << source;
    ASSERT_NEAR(fuzz, range->fuzz, EPSILON) << "Axis: " << axis << " Source: " << source;
}

void assertPointerCoords(const PointerCoords& coords, float x, float y, float pressure, float size,
                         float touchMajor, float touchMinor, float toolMajor, float toolMinor,
                         float orientation, float distance, float scaledAxisEpsilon) {
    ASSERT_NEAR(x, coords.getAxisValue(AMOTION_EVENT_AXIS_X), scaledAxisEpsilon);
    ASSERT_NEAR(y, coords.getAxisValue(AMOTION_EVENT_AXIS_Y), scaledAxisEpsilon);
    ASSERT_NEAR(pressure, coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), EPSILON);
    ASSERT_NEAR(size, coords.getAxisValue(AMOTION_EVENT_AXIS_SIZE), EPSILON);
    ASSERT_NEAR(touchMajor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), scaledAxisEpsilon);
    ASSERT_NEAR(touchMinor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), scaledAxisEpsilon);
    ASSERT_NEAR(toolMajor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), scaledAxisEpsilon);
    ASSERT_NEAR(toolMinor, coords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), scaledAxisEpsilon);
    ASSERT_NEAR(orientation, coords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION), EPSILON);
    ASSERT_NEAR(distance, coords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE), EPSILON);
}

} // namespace android
