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

@file:Suppress("DEPRECATION")

package androidx.compose.ui.platform

import androidx.compose.runtime.collection.mutableVectorOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.DefaultPointerButtons
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.InternalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.PrimaryPressedPointerButtons
import androidx.compose.ui.autofill.Autofill
import androidx.compose.ui.autofill.AutofillTree
import androidx.compose.ui.draganddrop.DragAndDropManager
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.FocusDirection.Companion.Enter
import androidx.compose.ui.focus.FocusDirection.Companion.Exit
import androidx.compose.ui.focus.FocusDirection.Companion.Next
import androidx.compose.ui.focus.FocusDirection.Companion.Previous
import androidx.compose.ui.focus.FocusOwner
import androidx.compose.ui.focus.FocusOwnerImpl
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Canvas
import androidx.compose.ui.graphics.GraphicsContext
import androidx.compose.ui.graphics.Matrix
import androidx.compose.ui.graphics.asComposeCanvas
import androidx.compose.ui.graphics.layer.GraphicsContext
import androidx.compose.ui.graphics.layer.GraphicsLayer
import androidx.compose.ui.input.InputMode.Companion.Keyboard
import androidx.compose.ui.input.InputModeManager
import androidx.compose.ui.input.InputModeManagerImpl
import androidx.compose.ui.input.key.Key.Companion.Back
import androidx.compose.ui.input.key.Key.Companion.DirectionCenter
import androidx.compose.ui.input.key.Key.Companion.Tab
import androidx.compose.ui.input.key.KeyEvent
import androidx.compose.ui.input.key.KeyEventType.Companion.KeyDown
import androidx.compose.ui.input.key.isShiftPressed
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.onKeyEvent
import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.input.key.type
import androidx.compose.ui.input.pointer.PointerEventType
import androidx.compose.ui.input.pointer.PointerIcon
import androidx.compose.ui.input.pointer.PointerIconService
import androidx.compose.ui.input.pointer.PointerInputEvent
import androidx.compose.ui.input.pointer.PointerInputEventProcessor
import androidx.compose.ui.input.pointer.PointerKeyboardModifiers
import androidx.compose.ui.input.pointer.PositionCalculator
import androidx.compose.ui.input.pointer.ProcessResult
import androidx.compose.ui.input.pointer.TestPointerInputEventData
import androidx.compose.ui.layout.Placeable
import androidx.compose.ui.layout.PlacementScope
import androidx.compose.ui.layout.RootMeasurePolicy
import androidx.compose.ui.modifier.ModifierLocalManager
import androidx.compose.ui.node.InternalCoreApi
import androidx.compose.ui.node.LayoutNode
import androidx.compose.ui.node.LayoutNodeDrawScope
import androidx.compose.ui.node.MeasureAndLayoutDelegate
import androidx.compose.ui.node.Owner
import androidx.compose.ui.node.OwnerSnapshotObserver
import androidx.compose.ui.node.RootForTest
import androidx.compose.ui.semantics.EmptySemanticsElement
import androidx.compose.ui.semantics.EmptySemanticsModifier
import androidx.compose.ui.semantics.SemanticsOwner
import androidx.compose.ui.text.font.createFontFamilyResolver
import androidx.compose.ui.text.input.TextInputService
import androidx.compose.ui.text.platform.FontLoader
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntRect
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.LayoutDirection
import kotlin.coroutines.CoroutineContext

private typealias Command = () -> Unit

@OptIn(
    ExperimentalComposeUiApi::class,
    InternalCoreApi::class,
    InternalComposeUiApi::class
)
internal class SkiaBasedOwner(
    private val platformInputService: PlatformInput,
    private val component: PlatformComponent,
    density: Density = Density(1f, 1f),
    override val coroutineContext: CoroutineContext,
    val isPopup: Boolean = false,
    val isFocusable: Boolean = true,
    val onDismissRequest: (() -> Unit)? = null,
    private val onPreviewKeyEvent: (KeyEvent) -> Boolean = { false },
    private val onKeyEvent: (KeyEvent) -> Boolean = { false },
) : Owner, RootForTest, SkiaRootForTest, PositionCalculator {

    internal fun isHovered(point: Offset): Boolean {
        val intOffset = IntOffset(point.x.toInt(), point.y.toInt())
        return bounds.contains(intOffset)
    }

    internal var accessibilityController: AccessibilityController? = null

    internal var bounds by mutableStateOf(IntRect.Zero)

    override var density by mutableStateOf(density)

    // TODO(demin): support RTL
    override val layoutDirection: LayoutDirection = LayoutDirection.Ltr

    override val sharedDrawScope = LayoutNodeDrawScope()

    private val rootSemanticsNode = EmptySemanticsModifier()
    private val semanticsModifier = EmptySemanticsElement(rootSemanticsNode)

    override val focusOwner: FocusOwner = FocusOwnerImpl(
        onRequestApplyChangesListener = ::registerOnEndApplyChangesListener,
        onRequestFocusForOwner = { _, _ -> true }, // TODO request focus from framework.
        onMoveFocusInterop = { _ -> true },
        onClearFocusForOwner = {}, // TODO clear focus from framework.
        onFocusRectInterop = { null },
        onLayoutDirection = { layoutDirection } // TODO(demin): RTL [onRtlPropertiesChanged].
    )

    // TODO: Set the input mode. For now we don't support touch mode, (always in Key mode).
    private val _inputModeManager = InputModeManagerImpl(
        initialInputMode = Keyboard,
        onRequestInputModeChange = {
            // TODO: Change the input mode programmatically. For now we just return true if the
            //  requested input mode is Keyboard mode.
            it == Keyboard
        }
    )
    override val inputModeManager: InputModeManager
        get() = _inputModeManager

    override val modifierLocalManager: ModifierLocalManager = ModifierLocalManager(this)

    // TODO: set/clear _windowInfo.isWindowFocused when the window gains/loses focus.
    private val _windowInfo: WindowInfoImpl = WindowInfoImpl()
    override val windowInfo: WindowInfo
        get() = _windowInfo

    // TODO(b/177931787) : Consider creating a KeyInputManager like we have for FocusManager so
    //  that this common logic can be used by all owners.
    private val keyInputModifier = Modifier.onKeyEvent {
        val focusDirection = getFocusDirection(it)
        if (focusDirection == null || it.type != KeyDown) return@onKeyEvent false

        // Consume the key event if we moved focus.
        focusOwner.moveFocus(focusDirection)
    }

    @Suppress("unused") // to be used in JB fork (not all prerequisite changes added yet)
    internal fun setCurrentKeyboardModifiers(modifiers: PointerKeyboardModifiers) {
        _windowInfo.keyboardModifiers = modifiers
    }

    var constraints: Constraints = Constraints()
        set(value) {
            field = value

            if (!isPopup) {
                this.bounds = IntRect(
                    IntOffset(bounds.left, bounds.top),
                    IntSize(constraints.maxWidth, constraints.maxHeight)
                )
            }
        }

    override val root = LayoutNode().also {
        it.measurePolicy = RootMeasurePolicy
        it.modifier = semanticsModifier
            .then(focusOwner.modifier)
            .then(keyInputModifier)
            .onPreviewKeyEvent(onPreviewKeyEvent)
            .onKeyEvent(onKeyEvent)
    }

    override val rootForTest = this

    override val snapshotObserver = OwnerSnapshotObserver { command ->
        onDispatchCommand?.invoke(command)
    }
    private val pointerInputEventProcessor = PointerInputEventProcessor(root)
    private val measureAndLayoutDelegate = MeasureAndLayoutDelegate(root)

    private val endApplyChangesListeners = mutableVectorOf<(() -> Unit)?>()

    init {
        snapshotObserver.startObserving()
        root.attach(this)
        focusOwner.focusTransactionManager.withNewTransaction {
            // TODO instead of taking focus here, call this when the owner gets focused.
            focusOwner.takeFocus(Enter, previouslyFocusedRect = null)
        }
    }

    fun dispose() {
        snapshotObserver.stopObserving()
        // we don't need to call root.detach() because root will be garbage collected
    }

    override val textInputService = TextInputService(platformInputService)

    override val softwareKeyboardController: SoftwareKeyboardController =
        DelegatingSoftwareKeyboardController(textInputService)

    @Deprecated(
        "fontLoader is deprecated, use fontFamilyResolver",
        replaceWith = ReplaceWith("fontFamilyResolver")
    )
    override val fontLoader = FontLoader()

    override val fontFamilyResolver = createFontFamilyResolver()

    override val hapticFeedBack = DefaultHapticFeedback()

    override val clipboardManager = PlatformClipboardManager()

    override val accessibilityManager = DefaultAccessibilityManager()
    override val graphicsContext: GraphicsContext = GraphicsContext()

    override val textToolbar = DefaultTextToolbar()

    override val semanticsOwner: SemanticsOwner = SemanticsOwner(root, rootSemanticsNode)

    override val dragAndDropManager: DragAndDropManager get() = TODO("Not yet implemented")

    override val autofillTree = AutofillTree()

    override val autofill: Autofill? get() = null

    override val viewConfiguration: ViewConfiguration = DefaultViewConfiguration(density)

    override fun sendKeyEvent(keyEvent: KeyEvent): Boolean =
        sendKeyEvent(platformInputService, focusOwner, keyEvent)

    override var showLayoutBounds = false

    override fun requestFocus() = true

    override fun onAttach(node: LayoutNode) = Unit

    override fun onDetach(node: LayoutNode) {
        measureAndLayoutDelegate.onNodeDetached(node)
        snapshotObserver.clear(node)
        needClearObservations = true
    }

    override val measureIteration: Long get() = measureAndLayoutDelegate.measureIteration

    private var needLayout = true
    private var needDraw = true

    val needRender get() = needLayout || needDraw || needSendSyntheticEvents
    var onNeedRender: (() -> Unit)? = null
    var onDispatchCommand: ((Command) -> Unit)? = null

    fun render(canvas: org.jetbrains.skia.Canvas) {
        needLayout = false
        measureAndLayout()
        sendSyntheticEvents()
        needDraw = false
        draw(canvas)
        clearInvalidObservations()
    }

    private var needClearObservations = false

    private fun clearInvalidObservations() {
        if (needClearObservations) {
            snapshotObserver.clearInvalidObservations()
            needClearObservations = false
        }
    }

    private fun requestLayout() {
        needLayout = true
        needDraw = true
        onNeedRender?.invoke()
    }

    private fun requestDraw() {
        needDraw = true
        onNeedRender?.invoke()
    }

    var contentSize = IntSize.Zero
        private set

    override val placementScope: Placeable.PlacementScope = PlacementScope(this)

    override fun measureAndLayout(sendPointerUpdate: Boolean) {
        measureAndLayoutDelegate.updateRootConstraints(constraints)
        if (
            measureAndLayoutDelegate.measureAndLayout(
                scheduleSyntheticEvents.takeIf { sendPointerUpdate }
            )
        ) {
            requestDraw()
        }
        measureAndLayoutDelegate.dispatchOnPositionedCallbacks()

        // Don't use mainOwner.root.width here, as it strictly coerced by [constraints]
        contentSize = IntSize(
            root.children.maxOfOrNull { it.outerCoordinator.measuredWidth } ?: 0,
            root.children.maxOfOrNull { it.outerCoordinator.measuredHeight } ?: 0,
        )
    }

    override fun measureAndLayout(layoutNode: LayoutNode, constraints: Constraints) {
        measureAndLayoutDelegate.measureAndLayout(layoutNode, constraints)
        measureAndLayoutDelegate.dispatchOnPositionedCallbacks()
    }

    override fun forceMeasureTheSubtree(layoutNode: LayoutNode, affectsLookahead: Boolean) {
        measureAndLayoutDelegate.forceMeasureTheSubtree(layoutNode, affectsLookahead)
    }

    override fun onRequestMeasure(
        layoutNode: LayoutNode,
        affectsLookahead: Boolean,
        forceRequest: Boolean,
        scheduleMeasureAndLayout: Boolean
    ) {
        if (affectsLookahead) {
            if (measureAndLayoutDelegate.requestLookaheadRemeasure(layoutNode, forceRequest) &&
                scheduleMeasureAndLayout
            ) {
                requestLayout()
            }
        } else if (measureAndLayoutDelegate.requestRemeasure(layoutNode, forceRequest) &&
            scheduleMeasureAndLayout
        ) {
            requestLayout()
        }
    }

    override fun onRequestRelayout(
        layoutNode: LayoutNode,
        affectsLookahead: Boolean,
        forceRequest: Boolean
    ) {
        if (affectsLookahead) {
            if (measureAndLayoutDelegate.requestLookaheadRelayout(layoutNode, forceRequest)) {
                requestLayout()
            }
        } else if (measureAndLayoutDelegate.requestRelayout(layoutNode, forceRequest)) {
            requestLayout()
        }
    }

    override fun requestOnPositionedCallback(layoutNode: LayoutNode) {
        measureAndLayoutDelegate.requestOnPositionedCallback(layoutNode)
        requestLayout()
    }

    override fun createLayer(
        drawBlock: (Canvas, GraphicsLayer?) -> Unit,
        invalidateParentLayer: () -> Unit,
        explicitLayer: GraphicsLayer?
    ) = SkiaLayer(
        density,
        invalidateParentLayer = {
            invalidateParentLayer()
            requestDraw()
        },
        drawBlock = drawBlock,
        onDestroy = { needClearObservations = true }
    )

    override fun onSemanticsChange() {
        accessibilityController?.onSemanticsChange()
    }

    override fun onLayoutChange(layoutNode: LayoutNode) {
        accessibilityController?.onLayoutChange(layoutNode)
    }

    override fun getFocusDirection(keyEvent: KeyEvent): FocusDirection? {
        return when (keyEvent.key) {
            Tab -> if (keyEvent.isShiftPressed) Previous else Next
            DirectionCenter -> Enter
            Back -> Exit
            else -> null
        }
    }

    override fun calculatePositionInWindow(localPosition: Offset): Offset = localPosition

    override fun calculateLocalPosition(positionInWindow: Offset): Offset = positionInWindow

    override fun localToScreen(localPosition: Offset): Offset = localPosition

    override fun localToScreen(localTransform: Matrix) {}

    override fun screenToLocal(positionOnScreen: Offset): Offset = positionOnScreen

    fun draw(canvas: org.jetbrains.skia.Canvas) {
        root.draw(canvas.asComposeCanvas(), null)
    }

    private var desiredPointerIcon: PointerIcon? = null

    private var needSendSyntheticEvents = false
    private var lastPointerEvent: PointerInputEvent? = null

    private val scheduleSyntheticEvents: () -> Unit = {
        // we can't send event synchronously, as we can have call of `measureAndLayout`
        // inside the event handler. So we can have a situation when we call event handler inside
        // event handler. And that can lead to unpredictable behaviour.
        // Nature of synthetic events doesn't require that they should be fired
        // synchronously on layout change.
        needSendSyntheticEvents = true
        onNeedRender?.invoke()
    }

    // TODO(demin) should we repeat all events, or only which are make sense?
    //  For example, touch Move after touch Release doesn't make sense,
    //  and an application can handle it in a wrong way
    //  Desktop doesn't support touch at the moment, but when it will, we should resolve this.
    private fun sendSyntheticEvents() {
        if (needSendSyntheticEvents) {
            needSendSyntheticEvents = false
            val lastPointerEvent = lastPointerEvent
            if (lastPointerEvent != null) {
                doProcessPointerInput(
                    PointerInputEvent(
                        PointerEventType.Move,
                        lastPointerEvent.uptime,
                        lastPointerEvent.pointers,
                        lastPointerEvent.buttons,
                        lastPointerEvent.keyboardModifiers,
                        lastPointerEvent.mouseEvent
                    )
                )
            }
        }
    }

    internal fun processPointerInput(event: PointerInputEvent): ProcessResult {
        measureAndLayout()
        sendSyntheticEvents()
        desiredPointerIcon = null
        lastPointerEvent = event
        return doProcessPointerInput(event)
    }

    private fun doProcessPointerInput(event: PointerInputEvent): ProcessResult {
        return pointerInputEventProcessor.process(
            event,
            this,
            isInBounds = event.pointers.all {
                it.position.x in 0f..root.width.toFloat() &&
                    it.position.y in 0f..root.height.toFloat()
            }
        ).also {
            if (it.dispatchedToAPointerInputModifier) {
                setPointerIcon(component, desiredPointerIcon)
            }
        }
    }

    override fun processPointerInput(timeMillis: Long, pointers: List<TestPointerInputEventData>) {
        val isPressed = pointers.any { it.down }
        processPointerInput(
            PointerInputEvent(
                PointerEventType.Unknown,
                timeMillis,
                pointers.map { it.toPointerInputEventData() },
                if (isPressed) PrimaryPressedPointerButtons else DefaultPointerButtons
            )
        )
    }

    override fun onEndApplyChanges() {
        // Listeners can add more items to the list and we want to ensure that they
        // are executed after being added, so loop until the list is empty
        while (endApplyChangesListeners.isNotEmpty()) {
            val size = endApplyChangesListeners.size
            for (i in 0 until size) {
                val listener = endApplyChangesListeners[i]
                // null out the item so that if the listener is re-added then we execute it again.
                endApplyChangesListeners[i] = null
                listener?.invoke()
            }
            // Remove all the items that were visited. Removing items shifts all items after
            // to the front of the list, so removing in a chunk is cheaper than removing one-by-one
            endApplyChangesListeners.removeRange(0, size)
        }
    }

    override fun registerOnEndApplyChangesListener(listener: () -> Unit) {
        if (listener !in endApplyChangesListeners) {
            endApplyChangesListeners += listener
        }
    }

    override fun registerOnLayoutCompletedListener(listener: Owner.OnLayoutCompletedListener) {
        measureAndLayoutDelegate.registerOnLayoutCompletedListener(listener)
        requestLayout()
    }

    override suspend fun textInputSession(
        session: suspend PlatformTextInputSessionScope.() -> Nothing
    ): Nothing {
        component.textInputSession(session)
    }

    // A Stub for the PointerIconService required in Owner.kt
    override val pointerIconService: PointerIconService =
        object : PointerIconService {
            override fun getIcon(): PointerIcon {
                return desiredPointerIcon ?: PointerIcon.Default
            }

            override fun setIcon(value: PointerIcon?) {
                desiredPointerIcon = value
            }
        }
}

internal expect fun sendKeyEvent(
    platformInputService: PlatformInput,
    focusOwner: FocusOwner,
    keyEvent: KeyEvent
): Boolean

internal expect fun setPointerIcon(
    containerCursor: PlatformComponentWithCursor?,
    icon: PointerIcon?
)
