/*
 * Copyright (c) 2016-present, lovebing.net.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

package org.lovebing.reactnative.baidumap.uimanager;

import android.os.Build;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;

import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.map.UiSettings;
import com.baidu.mapapi.model.LatLng;
import com.baidu.navisdk.adapter.BaiduNaviManagerFactory;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.annotations.ReactProp;

import org.lovebing.reactnative.baidumap.listener.MapListener;
import org.lovebing.reactnative.baidumap.listener.NaviMapListener;
import org.lovebing.reactnative.baidumap.model.LocationData;
import org.lovebing.reactnative.baidumap.support.ConvertUtils;
import org.lovebing.reactnative.baidumap.view.OverlayCluster;
import org.lovebing.reactnative.baidumap.view.OverlayMarker;
import org.lovebing.reactnative.baidumap.view.OverlayView;

import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@RequiresApi(api = Build.VERSION_CODES.N)
public class NaviMapViewManager extends ViewGroupManager<FrameLayout> {

    private NaviMapListener mapListener;
    private static Set<OverlayMarker> overlayMarkers = ConcurrentHashMap.newKeySet();
    private int childrenCount = 0;
    @Override
    public String getName() {
        return "BaiduNaviMapView";
    }
    MapView mapView;
    @Override
    public void onCatalystInstanceDestroy() {
        super.onCatalystInstanceDestroy();
        Log.i("MapViewManager", "onCatalystInstanceDestroy:" );

    }

    @Override
    public void onDropViewInstance(@NonNull FrameLayout view) {
        BaiduNaviManagerFactory.getMapManager().detach(view);
        BaiduNaviManagerFactory.getRouteResultManager().onDestroy();

        super.onDropViewInstance(view);
        Log.i("MapViewManager", "onDropViewInstance:" );
    }

    @Override
    public void addView(FrameLayout parent, View child, int index) {
        Log.i("MapViewManager", "addView:" + index);
        if (child instanceof OverlayView) {
            if (child instanceof OverlayMarker) {
                overlayMarkers.add((OverlayMarker) child);
            }
            if (child instanceof OverlayCluster) {
                //((OverlayCluster) child).setMapListener(mapListener);
            }
            ((OverlayView) child).addTopMap(this.mapView.getMap());
        }
        super.addView(parent, child, index);
    }

    @Override
    public void removeViewAt(FrameLayout parent, int index) {
        View child = parent.getChildAt(index);
        Log.i("MapViewManager", "removeViewAt:" + index + "," + child.getClass().getName());
        if (child instanceof OverlayView) {
            if (child instanceof OverlayMarker) {
                overlayMarkers.add((OverlayMarker) child);
            }
            ((OverlayView) child).removeFromMap(mapView.getMap());
        }
        super.removeViewAt(parent, index);
    }



    @Override
    protected FrameLayout createViewInstance(ThemedReactContext themedReactContext) {
        FrameLayout viewGroup = new FrameLayout(themedReactContext);
        //TextureMapView mapView = new TextureMapView(themedReactContext);
        Log.i("MapViewManager", "createViewInstance: getParent" );
         mapView = BaiduNaviManagerFactory.getMapManager().getMapView();
        if(viewGroup!=null  ){
            BaiduNaviManagerFactory.getMapManager().attach(viewGroup);
            BaiduNaviManagerFactory.getRouteResultManager().onCreate(themedReactContext.getCurrentActivity());
            BaiduNaviManagerFactory.getRouteResultManager().onResume();
        }
        BaiduMap map = mapView.getMap();
        mapListener = new NaviMapListener(mapView, themedReactContext);
        map.setOnMapStatusChangeListener(mapListener);
        map.setOnMapLoadedCallback(mapListener);
        map.setOnMapClickListener(mapListener);
        map.setOnMapDoubleClickListener(mapListener);
        map.setOnMarkerClickListener(mapListener);
        map.setOnMarkerDragListener(mapListener);
        return viewGroup;
    }

    @ReactProp(name = "zoomControlsVisible")
    public void setZoomControlsVisible(FrameLayout mapView, boolean zoomControlsVisible) {
        this.mapView.showZoomControls(zoomControlsVisible);
    }

    @ReactProp(name = "trafficEnabled")
    public void setTrafficEnabled(FrameLayout mapView, boolean trafficEnabled) {
        this. mapView.getMap().setTrafficEnabled(trafficEnabled);
    }

    @ReactProp(name = "baiduHeatMapEnabled")
    public void setBaiduHeatMapEnabled(FrameLayout mapView, boolean baiduHeatMapEnabled) {
        this.mapView.getMap().setBaiduHeatMapEnabled(baiduHeatMapEnabled);
    }

    @ReactProp(name = "mapType")
    public void setMapType(FrameLayout mapView, int mapType) {
        this.mapView.getMap().setMapType(mapType);
    }

    @ReactProp(name = "zoom")
    public void setZoom(FrameLayout mapView, float zoom) {
        MapStatus mapStatus = new MapStatus.Builder().zoom(zoom).build();
        MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newMapStatus(mapStatus);
        this. mapView.getMap().setMapStatus(mapStatusUpdate);
    }

    @ReactProp(name = "showsUserLocation")
    public void setShowsUserLocation(FrameLayout mapView, boolean showsUserLocation) {
        this. mapView.getMap().setMyLocationEnabled(showsUserLocation);
    }

    @ReactProp(name = "showMapPoi")
    public void showMapPoi(FrameLayout mapView, boolean showMapPoi) {
        this.  mapView.getMap().showMapPoi(showMapPoi);
    }

    @ReactProp(name = "locationData")
    public void setLocationData(FrameLayout mapView, ReadableMap readableMap) {
        LocationData locationData = ConvertUtils.convert(readableMap, LocationData.class);
        if (locationData == null || !locationData.isValid()) {
            return;
        }
        MyLocationData.Builder builder = new MyLocationData.Builder()
                .latitude(locationData.getLatitude())
                .longitude(locationData.getLongitude());
        if (locationData.getDirection() != null) {
            builder.direction(locationData.getDirection().floatValue());
        }
        if (locationData.getSpeed() != null) {
            builder.speed(locationData.getSpeed().floatValue());
        }
        this. mapView.getMap().setMyLocationData(builder.build());
    }

    @ReactProp(name = "zoomGesturesEnabled")
    public void setGesturesEnabled(FrameLayout mapView, boolean zoomGesturesEnabled) {
        UiSettings setting = this.mapView.getMap().getUiSettings();
        setting.setZoomGesturesEnabled(zoomGesturesEnabled);
    }

    @ReactProp(name = "scrollGesturesEnabled")
    public void setScrollEnabled(FrameLayout mapView, boolean scrollGesturesEnabled) {
        UiSettings setting = this.mapView.getMap().getUiSettings();
        setting.setScrollGesturesEnabled(scrollGesturesEnabled);
    }

    @ReactProp(name = "center")
    public void setCenter(FrameLayout mapView, ReadableMap position) {
        LocationData locationData = ConvertUtils.convert(position, LocationData.class);
        LatLng point = ConvertUtils.convert(locationData);
        if (point == null) {
            return;
        }
        MapStatus mapStatus = new MapStatus.Builder()
                .target(point)
                .build();
        MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newMapStatus(mapStatus);
        this.mapView.getMap().setMapStatus(mapStatusUpdate);
    }

    @ReactProp(name = "childrenCount")
    public void setChildrenCount(FrameLayout mapView, Integer childrenCount) {
        Log.i("MapViewManager", "childrenCount:" + childrenCount);
        this.childrenCount = childrenCount;
    }

    public static OverlayMarker findOverlayMaker(Marker marker) {
        for (OverlayMarker overlayMarker : overlayMarkers) {
            if (marker.equals(overlayMarker.getMarker())) {
                return overlayMarker;
            }
            if (marker.getPosition() != null && marker.getPosition().latitude == overlayMarker.getPosition().latitude
                    && marker.getPosition().longitude == overlayMarker.getPosition().longitude) {
                return overlayMarker;
            }
        }
        return null;
    }
}
