package com.humand.demo.modules.RNSwipeable

import android.util.TypedValue
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.module.annotations.ReactModule
import com.facebook.react.uimanager.ThemedReactContext
import com.facebook.react.uimanager.annotations.ReactProp
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.common.MapBuilder
import com.facebook.react.uimanager.ViewGroupManager
import java.lang.ref.WeakReference

internal fun dpToPx(view: android.view.View, dp: Float): Float {
    return TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        dp,
        view.resources.displayMetrics
    )
}

//Native module to close all swipeables from JS
@ReactModule(name = "RNSwipeableModule")
class RNSwipeableModule(
    reactContext: ReactApplicationContext
) : ReactContextBaseJavaModule(reactContext) {
    override fun getName() = "RNSwipeableModule"

    @ReactMethod
    fun resetAll() {
        val act = reactApplicationContext.currentActivity
        if (act != null) {
            act.runOnUiThread { RNSwipeableManager.closeAll() }
        } else {
            reactApplicationContext.runOnUiQueueThread { RNSwipeableManager.closeAll() }
        }
    }
}


@ReactModule(name = RNSwipeableManager.REACT_CLASS)
class RNSwipeableManager(
    private val reactContext: ReactApplicationContext
) : ViewGroupManager<RNSwipeableView>() {

    companion object {
        const val REACT_CLASS = "RNSwipeableView"

        @Volatile
        private var activeRef: WeakReference<RNSwipeableView>? = null

        fun onDragBegan(view: RNSwipeableView) {
            val prev = activeRef?.get()
            if (prev != null && prev !== view) {
                prev.closeFromCoordinator()
            }
            activeRef = WeakReference(view)
        }

        fun closeAll(){
            val prev = activeRef?.get()
            if(prev != null){
                prev.closeFromCoordinator()
            }
        }

        fun onClosed(view: RNSwipeableView) {
            val cur = activeRef?.get()
            if (cur === view) {
                activeRef = null
            }
        }
    }

    override fun getName(): String = REACT_CLASS

    override fun createViewInstance(reactContext: ThemedReactContext): RNSwipeableView {
        return RNSwipeableView(reactContext)
    }

    @ReactProp(name = "maxRightOffset", defaultFloat = 150f)
    fun setMaxOffsetRight(view: RNSwipeableView, value: Float) {
        view.maxOffsetRight = dpToPx(view, value)
    }

    @ReactProp(name = "maxLeftOffset", defaultFloat = 75f)
    fun setMaxOffsetLeft(view: RNSwipeableView, value: Float) {
        view.maxOffsetLeft = dpToPx(view, value)
    }

    @ReactProp(name = "thresholdOpenLeft", defaultFloat = 30f)
    fun setThresholdOpenLeft(view: RNSwipeableView, value: Float) {
        view.thresholdOpenLeft = dpToPx(view, value)
    }

    @ReactProp(name = "thresholdCloseLeft", defaultFloat = 30f)
    fun setThresholdCloseLeft(view: RNSwipeableView, value: Float) {
        view.thresholdCloseLeft = dpToPx(view, value)
    }

    @ReactProp(name = "thresholdOpenRight", defaultFloat = 30f)
    fun setThresholdOpenRight(view: RNSwipeableView, value: Float) {
        view.thresholdOpenRight = dpToPx(view, value)
    }

    @ReactProp(name = "thresholdCloseRight", defaultFloat = 30f)
    fun setThresholdCloseRight(view: RNSwipeableView, value: Float) {
        view.thresholdCloseRight = dpToPx(view, value)
    }

    override fun getCommandsMap(): MutableMap<String, Int> {
        return MapBuilder.of(
            "reset", 1,
        )
    }

    override fun receiveCommand(
        root: RNSwipeableView,
        commandId: Int,
        args: ReadableArray?
    ) {
        when (commandId) {
            1 -> root.reset()
        }
    }

    override fun addView(parent: RNSwipeableView, child: android.view.View, index: Int) {
        parent.addView(child, index)
    }

    override fun removeViewAt(parent: RNSwipeableView, index: Int) {
        parent.removeViewAt(index)
    }

    override fun removeAllViews(parent: RNSwipeableView) {
        parent.removeAllViews()
    }

    override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any> {
        val base = super.getExportedCustomDirectEventTypeConstants()
            ?: MapBuilder.newHashMap<String, Any>()

        base["topSwipeableBegan"] = MapBuilder.of("registrationName", "onSwipeableBegan")
        base["topSwipeableFinish"] = MapBuilder.of("registrationName", "onSwipeableFinish")

        return base
    }
}
