package com.shoyoo.react.anavi.paths import android.content.Context import android.graphics.Color import com.amap.api.maps.AMap import com.amap.api.maps.CameraUpdateFactory import com.amap.api.maps.model.* import com.amap.api.services.core.LatLonPoint import com.amap.api.services.route.* import com.amap.api.services.route.RouteSearch.OnRouteSearchListener import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.ReadableMap import com.facebook.react.bridge.WritableMap import com.facebook.react.uimanager.ThemedReactContext import com.facebook.react.uimanager.events.RCTEventEmitter import com.facebook.react.views.view.ReactViewGroup import com.shoyoo.react.anavi.maps.AMapOverlay import com.shoyoo.react.anavi.toBitmap abstract class AMapPath(context: Context) : ReactViewGroup(context), AMapOverlay, OnRouteSearchListener { private val markers = arrayListOf() private val polylines = arrayListOf() private var startMarker: Marker? = null private var endMarker: Marker? = null private val throughPointMarkers = arrayListOf() private val eventEmitter: RCTEventEmitter = (context as ThemedReactContext).getJSModule(RCTEventEmitter::class.java) open var startPoint: LatLng? = null set(value) { val oldValue = field field = value checkNeedCalculate(oldValue, value) } open var endPoint: LatLng? = null set(value) { val oldValue = field field = value checkNeedCalculate(oldValue, value) } open var drawPath = true open var pathWidth = 18f open var pathColor: Int = Color.parseColor("#537edc") open var nodeVisible: Boolean = true open var startTitle: String = "起点" open var endTitle: String = "终点" open var throughPointBitmapDescriptor: BitmapDescriptor? = null get() = field ?: defaultThroughPointBitmapDescriptor open var startBitmapDescriptor: BitmapDescriptor? = null get() = field ?: defaultStartBitmapDescriptor open var endBitmapDescriptor: BitmapDescriptor? = null get() = field ?: defaultEndBitmapDescriptor open var nodeBitmapDescriptor: BitmapDescriptor? = null get() = field ?: defaultNodeBitmapDescriptor open var wayPoints: List? = null open var avoidRegions: List>? = null open var avoidRoad: String? = "" var mode: Int = RouteSearch.DRIVEING_PLAN_DEFAULT var normalColor: Int = Color.GREEN var slowlyColor: Int = Color.YELLOW var blockedColor: Int = Color.RED var severeBlockedColor: Int = Color.parseColor("#990033") var otherColor: Int = Color.parseColor("#537edc") var throughPoints: List? = null set(value) { val oldValue = field field = value checkNeedCalculate(oldValue, value) } var throughPointMarkerVisible: Boolean = true set(value) { if (value == field) { return } field = value throughPointMarkers.forEach { it.isVisible = value } } var startMarkerIcon: ReadableMap? = null set(value) { nodeBitmapDescriptor = BitmapDescriptorFactory.fromBitmap(value?.toBitmap(context)) field = value } var endMarkerIcon: ReadableMap? = null set(value) { endBitmapDescriptor = BitmapDescriptorFactory.fromBitmap(value?.toBitmap(context)) field = value } var nodeMarkerIcon: ReadableMap? = null set(value) { nodeBitmapDescriptor = BitmapDescriptorFactory.fromBitmap(value?.toBitmap(context)) field = value } var throughPointMarkerIcon: ReadableMap? = null set(value) { throughPointBitmapDescriptor = BitmapDescriptorFactory.fromBitmap(value?.toBitmap(context)) field = value } protected var map: AMap? = null protected var routeSearch: RouteSearch = RouteSearch(context) protected abstract val defaultStartBitmapDescriptor: BitmapDescriptor protected abstract val defaultEndBitmapDescriptor: BitmapDescriptor protected abstract val defaultNodeBitmapDescriptor: BitmapDescriptor protected abstract val defaultThroughPointBitmapDescriptor: BitmapDescriptor open val bounds: LatLngBounds? get() { return if (startPoint == null || endPoint == null) { null } else { LatLngBounds.builder().apply { include(startPoint!!.clone()) include(endPoint!!.clone()) }.build() } } open fun zoomToSpan() { bounds.let { map?.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 300, 200, 10)) } } open var nodeMarkerVisible: Boolean = true set(value) { if (value == field) { return } field = value markers.forEach { it.isVisible = value } } abstract fun calculate() abstract fun draw() open fun clear() { startMarker?.remove() endMarker?.remove() markers.forEach { it.remove() } polylines.forEach { it.remove() } throughPointMarkers.forEach { it.remove() } startMarker = null endMarker = null markers.clear() polylines.clear() throughPointMarkers.clear() } fun emit(id: Int?, event: String, data: WritableMap = Arguments.createMap()) { id?.let { eventEmitter.receiveEvent(it, event, data) } } // region Implement OnRouteSearchListener override fun onBusRouteSearched(result: BusRouteResult?, code: Int) { } override fun onDriveRouteSearched(result: DriveRouteResult?, code: Int) { } override fun onWalkRouteSearched(result: WalkRouteResult?, code: Int) { } override fun onRideRouteSearched(result: RideRouteResult?, code: Int) { } // endregion override fun add(map: AMap) { this.map = map } override fun remove() { clear() } protected open fun checkNeedCalculate(oldValue: T?, newValue: T?): Boolean { if (oldValue?.equals(newValue) == true) { return false } calculate() return true } protected open fun checkNeedDraw(oldValue: T?, newValue: T?): Boolean { if (oldValue?.equals(newValue) == true) { return false } draw() return true } protected open fun addStartAndEndMarker() { startMarker?.remove() startMarker = map?.addMarker(MarkerOptions().apply { visible(nodeMarkerVisible) position(startPoint) icon(startBitmapDescriptor) title(startTitle) snippet("详细信息") }) endMarker?.remove() endMarker = map?.addMarker(MarkerOptions().apply { visible(nodeMarkerVisible) position(endPoint) icon(endBitmapDescriptor) title(endTitle) }) } protected open fun addThroughPointMarker() { if (map == null) { return } fun throughPointMarkerOption(point: LatLonPoint): MarkerOptions { return MarkerOptions().apply { position(LatLng(point.latitude, point.longitude)) visible(throughPointMarkerVisible) icon(throughPointBitmapDescriptor) } } throughPoints?.forEach { point -> if (point != null && map != null) { throughPointMarkers.add(map!!.addMarker(throughPointMarkerOption(point))) } } } protected open fun addNodeMarker(markerOptions: MarkerOptions) = markers.add(map!!.addMarker(markerOptions)) protected open fun addPolyline(polylineOptions: PolylineOptions) = polylines.add(map!!.addPolyline(polylineOptions)) }