/*
 * Copyright (C) 2004, 2006-2011, 2014, 2019 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#import "config.h"
#import "PlatformEventFactoryIOS.h"

#if PLATFORM(IOS_FAMILY)

#import "IntPoint.h"
#import "KeyEventCocoa.h"
#import "KeyEventCodesIOS.h"
#import "Logging.h"
#import "WAKAppKitStubs.h"
#import "WebEvent.h"
#import "WindowsKeyboardCodes.h"
#import <wtf/Optional.h>
#import <wtf/WallTime.h>

namespace WebCore {

static OptionSet<PlatformEvent::Modifier> modifiersForEvent(WebEvent *event)
{
    OptionSet<PlatformEvent::Modifier> modifiers;

    if (event.modifierFlags & WebEventFlagMaskShiftKey)
        modifiers.add(PlatformEvent::Modifier::ShiftKey);
    if (event.modifierFlags & WebEventFlagMaskControlKey)
        modifiers.add(PlatformEvent::Modifier::ControlKey);
    if (event.modifierFlags & WebEventFlagMaskOptionKey)
        modifiers.add(PlatformEvent::Modifier::AltKey);
    if (event.modifierFlags & WebEventFlagMaskCommandKey)
        modifiers.add(PlatformEvent::Modifier::MetaKey);
    if (event.modifierFlags & WebEventFlagMaskLeftCapsLockKey)
        modifiers.add(PlatformEvent::Modifier::CapsLockKey);

    return modifiers;
}

static inline IntPoint pointForEvent(WebEvent *event)
{
    return IntPoint(event.locationInWindow);
}

static inline IntPoint globalPointForEvent(WebEvent *event)
{
    // iOS WebKit works as if it is full screen. Therefore Web coords are Global coords.
    return pointForEvent(event);
}

static PlatformEvent::Type mouseEventType(WebEvent *event)
{
    switch (event.type) {
    case WebEventMouseDown:
        return PlatformEvent::MousePressed;
    case WebEventMouseUp:
        return PlatformEvent::MouseReleased;
    case WebEventMouseMoved:
        return PlatformEvent::MouseMoved;
    default:
        ASSERT_NOT_REACHED();
        return PlatformEvent::MousePressed;
    }
}

class PlatformMouseEventBuilder : public PlatformMouseEvent {
public:
    PlatformMouseEventBuilder(WebEvent *event)
    {
        m_type = mouseEventType(event);
        m_timestamp = WallTime::now();

        m_position = pointForEvent(event);
        m_globalPosition = globalPointForEvent(event);
        m_button = LeftButton; // This has always been the LeftButton on iOS.
        m_clickCount = 1; // This has always been 1 on iOS.
        m_modifiers = modifiersForEvent(event);
    }
};

PlatformMouseEvent PlatformEventFactory::createPlatformMouseEvent(WebEvent *event)
{
    return PlatformMouseEventBuilder(event);
}

class PlatformWheelEventBuilder : public PlatformWheelEvent {
public:
    PlatformWheelEventBuilder(WebEvent *event)
    {
        ASSERT(event.type == WebEventScrollWheel);

        m_type = PlatformEvent::Wheel;
        m_timestamp = WallTime::now();

        m_position = pointForEvent(event);
        m_globalPosition = globalPointForEvent(event);
        m_deltaX = event.deltaX;
        m_deltaY = event.deltaY;
        m_granularity = ScrollByPixelWheelEvent; // iOS only supports continuous (pixel-mode) scrolling.
    }
};

PlatformWheelEvent PlatformEventFactory::createPlatformWheelEvent(WebEvent *event)
{
    return PlatformWheelEventBuilder(event);
}

String keyIdentifierForKeyEvent(WebEvent *event)
{
    if (event.keyboardFlags & WebEventKeyboardInputModifierFlagsChanged) {
        switch (event.keyCode) {
        case VK_LWIN: // Left Command
        case VK_APPS: // Right Command
            return "Meta"_s;

        case VK_CAPITAL: // Caps Lock
            return "CapsLock"_s;

        case VK_LSHIFT: // Left Shift
        case VK_RSHIFT: // Right Shift
            return "Shift"_s;

        case VK_LMENU: // Left Alt
        case VK_RMENU: // Right Alt
            return "Alt"_s;

        case VK_LCONTROL: // Left Ctrl
        case VK_RCONTROL: // Right Ctrl
            return "Control"_s;

        default:
            ASSERT_NOT_REACHED();
            return emptyString();
        }
    }
    NSString *characters = event.charactersIgnoringModifiers;
    if ([characters length] != 1) {
        LOG(Events, "received an unexpected number of characters in key event: %u", [characters length]);
        return "Unidentified"_s;
    }
    return keyIdentifierForCharCode([characters characterAtIndex:0]);
}

String keyForKeyEvent(WebEvent *event)
{
    if (event.keyboardFlags & WebEventKeyboardInputModifierFlagsChanged) {
        switch (event.keyCode) {
        case VK_LWIN: // Left Command
        case VK_APPS: // Right Command
            return "Meta"_s;

        case VK_CAPITAL: // Caps Lock
            return "CapsLock"_s;

        case VK_LSHIFT: // Left Shift
        case VK_RSHIFT: // Right Shift
            return "Shift"_s;

        case VK_LMENU: // Left Alt
        case VK_RMENU: // Right Alt
            return "Alt"_s;

        case VK_LCONTROL: // Left Ctrl
        case VK_RCONTROL: // Right Ctrl
            return "Control"_s;

        default:
            ASSERT_NOT_REACHED();
            return "Unidentified"_s;
        }
    }

    // If more than one key is being pressed and the key combination includes one or more modifier keys
    // that result in the key no longer producing a printable character (e.g., Control + a), then the
    // key value should be the printable key value that would have been produced if the key had been
    // typed with the default keyboard layout with no modifier keys except for Shift and AltGr applied.
    // See <https://www.w3.org/TR/2015/WD-uievents-20151215/#keys-guidelines>.
    bool isControlDown = event.modifierFlags & WebEventFlagMaskControlKey;
    NSString *characters = isControlDown ? event.charactersIgnoringModifiers : event.characters;
    auto length = [characters length];
    // characters return an empty string for dead keys.
    // https://developer.apple.com/reference/appkit/nsevent/1534183-characters
    // "Dead" is defined here https://w3c.github.io/uievents-key/#keys-composition.
    if (!length)
        return "Dead"_s;
    if (length > 1)
        return characters;
    return keyForCharCode([characters characterAtIndex:0]);
}

// https://w3c.github.io/uievents-code/
String codeForKeyEvent(WebEvent *event)
{
    switch (event.keyCode) {
    // Keys in the alphanumeric section.
    case VK_OEM_3: return "Backquote"_s;
    case VK_OEM_5: return "Backslash"_s;
    case VK_BACK: return "Backspace"_s;
    case VK_OEM_4: return "BracketLeft"_s;
    case VK_OEM_6: return "BracketRight"_s;
    case VK_OEM_COMMA: return "Comma"_s;
    case VK_0: return "Digit0"_s;
    case VK_1: return "Digit1"_s;
    case VK_2: return "Digit2"_s;
    case VK_3: return "Digit3"_s;
    case VK_4: return "Digit4"_s;
    case VK_5: return "Digit5"_s;
    case VK_6: return "Digit6"_s;
    case VK_7: return "Digit7"_s;
    case VK_8: return "Digit8"_s;
    case VK_9: return "Digit9"_s;
    case VK_OEM_PLUS: return "Equal"_s;
    case VK_OEM_102: return "IntlBackslash"_s;
    // IntlRo.
    // IntlYen.
    case VK_A: return "KeyA"_s;
    case VK_B: return "KeyB"_s;
    case VK_C: return "KeyC"_s;
    case VK_D: return "KeyD"_s;
    case VK_E: return "KeyE"_s;
    case VK_F: return "KeyF"_s;
    case VK_G: return "KeyG"_s;
    case VK_H: return "KeyH"_s;
    case VK_I: return "KeyI"_s;
    case VK_J: return "KeyJ"_s;
    case VK_K: return "KeyK"_s;
    case VK_L: return "KeyL"_s;
    case VK_M: return "KeyM"_s;
    case VK_N: return "KeyN"_s;
    case VK_O: return "KeyO"_s;
    case VK_P: return "KeyP"_s;
    case VK_Q: return "KeyQ"_s;
    case VK_R: return "KeyR"_s;
    case VK_S: return "KeyS"_s;
    case VK_T: return "KeyT"_s;
    case VK_U: return "KeyU"_s;
    case VK_V: return "KeyV"_s;
    case VK_W: return "KeyW"_s;
    case VK_X: return "KeyX"_s;
    case VK_Y: return "KeyY"_s;
    case VK_Z: return "KeyZ"_s;
    case VK_OEM_MINUS: return "Minus"_s;
    case VK_OEM_PERIOD: return "Period"_s;
    case VK_OEM_7: return "Quote"_s;
    case VK_OEM_1: return "Semicolon"_s;
    case VK_OEM_2: return "Slash"_s;

    // Functional keys in alphanumeric section.
    case VK_LMENU: return "AltLeft"_s;
    case VK_RMENU: return "AltRight"_s;
    case VK_CAPITAL: return "CapsLock"_s;
    // ContextMenu.
    case VK_LCONTROL: return "ControlLeft"_s;
    case VK_RCONTROL: return "ControlRight"_s;
    case VK_RETURN: return "Enter"_s; //  Labeled Return on Apple keyboards.
    case VK_LWIN: return "MetaLeft"_s;
    case VK_APPS: return "MetaRight"_s;
    case VK_LSHIFT: return "ShiftLeft"_s;
    case VK_RSHIFT: return "ShiftRight"_s;
    case VK_SPACE: return "Space"_s;
    case VK_TAB: return "Tab"_s;

    // Functional keys found on Japanese and Korean keyboards.
    // Convert.
    case VK_KANA: return "KanaMode"_s;
    // Lang1.
    // Lang2.
    // Lang3.
    // Lang4.
    // Lang5.
    // NonConvert.

    // Keys in the ControlPad section.
    // Delete
    case VK_END: return "End"_s;
    case VK_HELP: return "Help"_s;
    case VK_HOME: return "Home"_s;
    // Insert: Not present on Apple keyboards.
    case VK_NEXT: return "PageDown"_s;
    case VK_PRIOR: return "PageUp"_s;

    // Keys in the ArrowPad section.
    case VK_DOWN: return "ArrowDown"_s;
    case VK_LEFT: return "ArrowLeft"_s;
    case VK_RIGHT: return "ArrowRight"_s;
    case VK_UP: return "ArrowUp"_s;

    // Keys in the Numpad section.
    case VK_NUMLOCK: return "NumLock"_s;
    case VK_NUMPAD0: return "Numpad0"_s;
    case VK_NUMPAD1: return "Numpad1"_s;
    case VK_NUMPAD2: return "Numpad2"_s;
    case VK_NUMPAD3: return "Numpad3"_s;
    case VK_NUMPAD4: return "Numpad4"_s;
    case VK_NUMPAD5: return "Numpad5"_s;
    case VK_NUMPAD6: return "Numpad6"_s;
    case VK_NUMPAD7: return "Numpad7"_s;
    case VK_NUMPAD8: return "Numpad8"_s;
    case VK_NUMPAD9: return "Numpad9"_s;
    case VK_ADD: return "NumpadAdd"_s;
    // NumpadBackspace.
    // NumpadClear.
    // NumpadClearEntry.
    case VK_SEPARATOR: return "NumpadComma"_s; // On JIS keyboard
    case VK_DECIMAL: return "NumpadDecimal"_s;
    case VK_DIVIDE: return "NumpadDivide"_s;
    // NumpadEnter.
    case VK_CLEAR: return "NumpadEqual"_s;
    // NumpadHash.
    // NumpadMemoryAdd.
    // NumpadMemoryClear.
    // NumpadMemoryRecall.
    // NumpadMemoryStore.
    // NumpadMemorySubtract.
    case VK_MULTIPLY: return "NumpadMultiply"_s;
    // NumpadParenLeft.
    // NumpadParenRight.
    // NumpadStar: The specification says to use "NumpadMultiply" for the * key on numeric keypads.
    case VK_SUBTRACT: return "NumpadSubtract"_s;

    // Keys in the Function section.
    case VK_ESCAPE: return "Escape"_s;
    case VK_F1: return "F1"_s;
    case VK_F2: return "F2"_s;
    case VK_F3: return "F3"_s;
    case VK_F4: return "F4"_s;
    case VK_F5: return "F5"_s;
    case VK_F6: return "F6"_s;
    case VK_F7: return "F7"_s;
    case VK_F8: return "F8"_s;
    case VK_F9: return "F9"_s;
    case VK_F10: return "F10"_s;
    case VK_F11: return "F11"_s;
    case VK_F12: return "F12"_s;
    case VK_F13: return "F13"_s;
    case VK_F14: return "F14"_s;
    case VK_F15: return "F15"_s;
    case VK_F16: return "F16"_s;
    case VK_F17: return "F17"_s;
    case VK_F18: return "F18"_s;
    case VK_F19: return "F19"_s;
    case VK_F20: return "F20"_s;
    // Fn: This is typically a hardware key that does not generate a separate code.
    // FnLock.
    // PrintScreen.
    // ScrollLock.
    // Pause.

    // Media keys.
    // BrowserBack.
    // BrowserFavorites.
    // BrowserForward.
    // BrowserHome.
    // BrowserRefresh.
    // BrowserSearch.
    // BrowserStop.
    // Eject.
    // LaunchApp1.
    // LaunchApp2.
    // LaunchMail.
    // MediaPlayPause.
    // MediaSelect.
    // MediaStop.
    // MediaTrackNext.
    // MediaTrackPrevious.
    // Power.
    // Sleep.
    case VK_VOLUME_DOWN: return "AudioVolumeDown"_s;
    case VK_VOLUME_MUTE: return "AudioVolumeMute"_s;
    case VK_VOLUME_UP: return "AudioVolumeUp"_s;
    // WakeUp.

    // Legacy modifier keys.
    // Hyper.
    // Super.
    // Turbo.

    // Legacy process control keys.
    // Abort.
    // Resume.
    // Suspend.

    // Legacy editing keys.
    // Again.
    // Copy.
    // Cut.
    // Find.
    // Open.
    // Paste.
    // Props.
    // Select.
    // Undo.

    // Keys found on international keyboards.
    // Hiragana.
    // Katakana.

    default:
        return "Unidentified"_s;
    }
}

static bool isKeypadEvent(WebEvent* event)
{
    // Check that this is the type of event that has a keyCode.
    if (event.type != WebEventKeyDown && event.type != WebEventKeyUp)
        return false;

    switch (event.keyCode) {
    case VK_CLEAR: // Num Pad Clear
    case VK_OEM_PLUS: // Num Pad =
    case VK_DIVIDE:
    case VK_MULTIPLY:
    case VK_SUBTRACT:
    case VK_ADD:
    case VK_RETURN: // Num Pad Enter
    case VK_DECIMAL: // Num Pad .
    case VK_SEPARATOR: // Num Pad , (on JIS keyboard)
    case VK_NUMPAD0:
    case VK_NUMPAD1:
    case VK_NUMPAD2:
    case VK_NUMPAD3:
    case VK_NUMPAD4:
    case VK_NUMPAD5:
    case VK_NUMPAD6:
    case VK_NUMPAD7:
    case VK_NUMPAD8:
    case VK_NUMPAD9:
        return true;
    }
    return false;
}

int windowsKeyCodeForKeyEvent(WebEvent* event)
{
    if (event.keyboardFlags & WebEventKeyboardInputModifierFlagsChanged)
        return event.keyCode;

    // There are several kinds of characters for which we produce key code from char code:
    // 1. Roman letters. Windows keyboard layouts affect both virtual key codes and character codes for these,
    //    so e.g. 'A' gets the same keyCode on QWERTY, AZERTY or Dvorak layouts.
    // 2. Keys for which there is no known iOS virtual key codes, like PrintScreen.
    // 3. Certain punctuation keys. On Windows, these are also remapped depending on current keyboard layout,
    //    but see comment in windowsKeyCodeForCharCode().
    if (!isKeypadEvent(event) && (event.type == WebEventKeyDown || event.type == WebEventKeyUp)) {
        // Cmd switches Roman letters for Dvorak-QWERTY layout, so try modified characters first.
        NSString *string = event.characters;
        int code = string.length > 0 ? windowsKeyCodeForCharCode([string characterAtIndex:0]) : 0;
        if (code)
            return code;

        // Ctrl+A on an AZERTY keyboard would get VK_Q keyCode if we relied on -[WebEvent keyCode] below.
        string = event.charactersIgnoringModifiers;
        code = string.length > 0 ? windowsKeyCodeForCharCode([string characterAtIndex:0]) : 0;
        if (code)
            return code;
    }

    // Use iOS virtual key code directly for any keys not handled above.
    // E.g. the key next to Caps Lock has the same Event.keyCode on U.S. keyboard ('A') and on
    // Russian keyboard (CYRILLIC LETTER EF).
    return event.keyCode;
}

class PlatformKeyboardEventBuilder : public PlatformKeyboardEvent {
public:
    PlatformKeyboardEventBuilder(WebEvent *event)
    {
        ASSERT(event.type == WebEventKeyDown || event.type == WebEventKeyUp);

        m_type = (event.type == WebEventKeyUp ? PlatformEvent::KeyUp : PlatformEvent::KeyDown);
        m_modifiers = modifiersForEvent(event);
        m_timestamp = WallTime::now();

        if (event.keyboardFlags & WebEventKeyboardInputModifierFlagsChanged) {
            m_text = emptyString();
            m_unmodifiedText = emptyString();
            m_autoRepeat = false;
        } else {
            m_text = event.characters;
            m_unmodifiedText = event.charactersIgnoringModifiers;
            m_autoRepeat = event.isKeyRepeating;
        }
        m_key = keyForKeyEvent(event);
        m_code = codeForKeyEvent(event);
        m_keyIdentifier = keyIdentifierForKeyEvent(event);
        m_windowsVirtualKeyCode = windowsKeyCodeForKeyEvent(event);
        m_isKeypad = false; // iOS does not distinguish the numpad. See <rdar://problem/7190835>.
        m_isSystemKey = false;
        m_Event = event;

        // Always use 13 for Enter/Return -- we don't want to use AppKit's different character for Enter.
        if (m_windowsVirtualKeyCode == '\r') {
            m_text = "\r";
            m_unmodifiedText = "\r";
        }

        // The adjustments below are only needed in backward compatibility mode, but we cannot tell what mode we are in from here.

        // Turn 0x7F into 8, because backspace needs to always be 8.
        if (m_text == "\x7F")
            m_text = "\x8";
        if (m_unmodifiedText == "\x7F")
            m_unmodifiedText = "\x8";
        // Always use 9 for tab -- we don't want to use AppKit's different character for shift-tab.
        if (m_windowsVirtualKeyCode == 9) {
            m_text = "\x9";
            m_unmodifiedText = "\x9";
        }
    }
};

PlatformKeyboardEvent PlatformEventFactory::createPlatformKeyboardEvent(WebEvent *event)
{
    return PlatformKeyboardEventBuilder(event);
}

#if ENABLE(TOUCH_EVENTS)
static PlatformTouchPoint::TouchPhaseType convertTouchPhase(NSNumber *touchPhaseNumber)
{
    WebEventTouchPhaseType touchPhase = static_cast<WebEventTouchPhaseType>([touchPhaseNumber unsignedIntValue]);
    switch (touchPhase) {
    case WebEventTouchPhaseBegan:
        return PlatformTouchPoint::TouchPhaseBegan;
    case WebEventTouchPhaseMoved:
        return PlatformTouchPoint::TouchPhaseMoved;
    case WebEventTouchPhaseStationary:
        return PlatformTouchPoint::TouchPhaseStationary;
    case WebEventTouchPhaseEnded:
        return PlatformTouchPoint::TouchPhaseEnded;
    case WebEventTouchPhaseCancelled:
        return PlatformTouchPoint::TouchPhaseCancelled;
    default:
        ASSERT_NOT_REACHED();
    }
    return PlatformTouchPoint::TouchPhaseBegan;
}

static PlatformEvent::Type touchEventType(WebEvent *event)
{
    switch (event.type) {
    case WebEventTouchBegin:
        return PlatformEvent::TouchStart;
    case WebEventTouchEnd:
        return PlatformEvent::TouchEnd;
    case WebEventTouchCancel:
        return PlatformEvent::TouchCancel;
    case WebEventTouchChange:
        return PlatformEvent::TouchMove;
    default:
        ASSERT_NOT_REACHED();
        return PlatformEvent::TouchCancel;
    }
}
    
static PlatformTouchPoint::TouchPhaseType touchPhaseFromPlatformEventType(PlatformEvent::Type type)
{
    switch (type) {
    case PlatformEvent::TouchStart:
        return PlatformTouchPoint::TouchPhaseBegan;
    case PlatformEvent::TouchMove:
        return PlatformTouchPoint::TouchPhaseMoved;
    case PlatformEvent::TouchEnd:
        return PlatformTouchPoint::TouchPhaseEnded;
    default:
        ASSERT_NOT_REACHED();
        return PlatformTouchPoint::TouchPhaseCancelled;
    }
}

class PlatformTouchPointBuilder : public PlatformTouchPoint {
public:
    PlatformTouchPointBuilder(unsigned identifier, const IntPoint& location, TouchPhaseType phase)
        : PlatformTouchPoint(identifier, location, phase)
    {
    }
};

class PlatformTouchEventBuilder : public PlatformTouchEvent {
public:
    PlatformTouchEventBuilder(WebEvent *event)
    {
        m_type = touchEventType(event);
        m_modifiers = modifiersForEvent(event);
        m_timestamp = WallTime::fromRawSeconds(event.timestamp);

        m_gestureScale = event.gestureScale;
        m_gestureRotation = event.gestureRotation;
        m_isGesture = event.isGesture;
        m_position = pointForEvent(event);
        m_globalPosition = globalPointForEvent(event);

        unsigned touchCount = event.touchCount;
        m_touchPoints.reserveInitialCapacity(touchCount);
        for (unsigned i = 0; i < touchCount; ++i) {
            unsigned identifier = [(NSNumber *)[event.touchIdentifiers objectAtIndex:i] unsignedIntValue];
            IntPoint location = IntPoint([(NSValue *)[event.touchLocations objectAtIndex:i] pointValue]);
            PlatformTouchPoint::TouchPhaseType touchPhase = convertTouchPhase([event.touchPhases objectAtIndex:i]);
            m_touchPoints.uncheckedAppend(PlatformTouchPointBuilder(identifier, location, touchPhase));
        }
    }
    
    PlatformTouchEventBuilder(PlatformEvent::Type type, IntPoint location)
    {
        m_type = type;
        m_timestamp = WallTime::now();
        
        m_gestureScale = 1;
        m_gestureRotation = 0;
        m_isGesture = 0;
        m_position = location;
        m_globalPosition = location;
        m_isPotentialTap = true;
        
        unsigned touchCount = 1;
        m_touchPoints.reserveInitialCapacity(touchCount);
        for (unsigned i = 0; i < touchCount; ++i)
            m_touchPoints.uncheckedAppend(PlatformTouchPointBuilder(1, location, touchPhaseFromPlatformEventType(type)));
    }
};

PlatformTouchEvent PlatformEventFactory::createPlatformTouchEvent(WebEvent *event)
{
    return PlatformTouchEventBuilder(event);
}
    
PlatformTouchEvent PlatformEventFactory::createPlatformSimulatedTouchEvent(PlatformEvent::Type type, IntPoint location)
{
    return PlatformTouchEventBuilder(type, location);
}

#endif // ENABLE(TOUCH_EVENTS)

} // namespace WebCore

#endif // PLATFORM(IOS_FAMILY)
