/*
 * Copyright (C) 2015 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 "InputDevice.h"

#include <memory>

#include <linux/input.h>

#include <gtest/gtest.h>

#include <utils/Timers.h>

#include "InputHub.h"
#include "InputMocks.h"
#include "MockInputHost.h"

// # of milliseconds to allow for timing measurements
#define TIMING_TOLERANCE_MS 25


using ::testing::_;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::ReturnNull;

namespace android {
namespace tests {

class EvdevDeviceTest : public ::testing::Test {
protected:
    virtual void SetUp() {
        // Creating device identifiers and definitions should always happen.
        EXPECT_CALL(mHost, createDeviceIdentifier(_, _, _, _, _))
            .WillOnce(ReturnNull());
        EXPECT_CALL(mHost, createDeviceDefinition())
            .WillOnce(Return(&mDeviceDef));
        // InputMappers may cause any of these to be called, but we are not
        // testing these here.
        ON_CALL(mHost, createInputReportDefinition())
            .WillByDefault(Return(&mReportDef));
        ON_CALL(mHost, createOutputReportDefinition())
            .WillByDefault(Return(&mReportDef));
        ON_CALL(mHost, registerDevice(_, _))
            .WillByDefault(ReturnNull());
    }

    MockInputHost mHost;
    // Ignore uninteresting calls on the report definitions by using NiceMocks.
    NiceMock<MockInputReportDefinition> mReportDef;
    NiceMock<MockInputDeviceDefinition> mDeviceDef;
};

TEST_F(EvdevDeviceTest, testWrongClockCorrection) {
    auto node = std::make_shared<MockInputDeviceNode>();
    auto device = std::make_unique<EvdevDevice>(&mHost, node);
    ASSERT_TRUE(device != nullptr);

    auto now = systemTime(SYSTEM_TIME_MONOTONIC);

    // Input event that supposedly comes from 1 minute in the future. In
    // reality, the timestamps would be much further off.
    InputEvent event = { now + s2ns(60), EV_KEY, KEY_HOME, 1 };

    device->processInput(event, now);

    EXPECT_NEAR(now, event.when, ms2ns(TIMING_TOLERANCE_MS));
}

TEST_F(EvdevDeviceTest, testClockCorrectionOk) {
    auto node = std::make_shared<MockInputDeviceNode>();
    auto device = std::make_unique<EvdevDevice>(&mHost, node);
    ASSERT_TRUE(device != nullptr);

    auto now = systemTime(SYSTEM_TIME_MONOTONIC);

    // Input event from now, but will be reported as if it came early.
    InputEvent event = { now, EV_KEY, KEY_HOME, 1 };

    // event_time parameter is 11 seconds in the past, so it looks like we used
    // the wrong clock.
    device->processInput(event, now - s2ns(11));

    EXPECT_NEAR(now, event.when, ms2ns(TIMING_TOLERANCE_MS));
}

TEST_F(EvdevDeviceTest, testN7v2Touchscreen) {
    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getElanTouchscreen());
    auto device = std::make_unique<EvdevDevice>(&mHost, node);
    EXPECT_EQ(INPUT_DEVICE_CLASS_TOUCH|INPUT_DEVICE_CLASS_TOUCH_MT,
            device->getInputClasses());
}

TEST_F(EvdevDeviceTest, testN7v2ButtonJack) {
    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getButtonJack());
    auto device = std::make_unique<EvdevDevice>(&mHost, node);
    EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
}

TEST_F(EvdevDeviceTest, testN7v2HeadsetJack) {
    // Eventually these mock device tests will all expect these calls. For now
    // only the SwitchInputMapper has been implemented.
    // TODO: move this expectation out to a common function
    EXPECT_CALL(mHost, createInputReportDefinition());
    EXPECT_CALL(mHost, createOutputReportDefinition());
    EXPECT_CALL(mHost, freeReportDefinition(_));
    EXPECT_CALL(mHost, registerDevice(_, _));

    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getHeadsetJack());
    auto device = std::make_unique<EvdevDevice>(&mHost, node);
    EXPECT_EQ(INPUT_DEVICE_CLASS_SWITCH, device->getInputClasses());
}

TEST_F(EvdevDeviceTest, testN7v2H2wButton) {
    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getH2wButton());
    auto device = std::make_unique<EvdevDevice>(&mHost, node);
    EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
}

TEST_F(EvdevDeviceTest, testN7v2GpioKeys) {
    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexus7v2::getGpioKeys());
    auto device = std::make_unique<EvdevDevice>(&mHost, node);
    EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
}

TEST_F(EvdevDeviceTest, testNexusPlayerGpioKeys) {
    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexusPlayer::getGpioKeys());
    auto device = std::make_unique<EvdevDevice>(&mHost, node);
    EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
}

TEST_F(EvdevDeviceTest, testNexusPlayerMidPowerBtn) {
    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexusPlayer::getMidPowerBtn());
    auto device = std::make_unique<EvdevDevice>(&mHost, node);
    EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
}

TEST_F(EvdevDeviceTest, testNexusRemote) {
    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexusPlayer::getNexusRemote());
    auto device = std::make_unique<EvdevDevice>(&mHost, node);
    EXPECT_EQ(INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
}

TEST_F(EvdevDeviceTest, testAsusGamepad) {
    auto node = std::shared_ptr<MockInputDeviceNode>(MockNexusPlayer::getAsusGamepad());
    auto device = std::make_unique<EvdevDevice>(&mHost, node);
    EXPECT_EQ(INPUT_DEVICE_CLASS_JOYSTICK|INPUT_DEVICE_CLASS_KEYBOARD, device->getInputClasses());
}

TEST_F(EvdevDeviceTest, testMocks) {
    auto node = std::make_shared<MockInputDeviceNode>();
    auto device = std::make_unique<EvdevDevice>(&mHost, node);
}

}  // namespace tests
}  // namespace android
