package com.airbnb.android.react.maps.common;

import android.view.ViewGroup;

import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.ViewGroupManager;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Nullable;

/**
 * Created by jiaming on 2/15/17.
 */

public abstract class AirMapManager<T extends ViewGroup & IAirMapView> extends ViewGroupManager<T> {
    private static final int ANIMATE_TO_REGION = 1;
    private static final int ANIMATE_TO_COORDINATE = 2;
    private static final int FIT_TO_ELEMENTS = 3;
    private static final int FIT_TO_SUPPLIED_MARKERS = 4;
    private static final int FIT_TO_COORDINATES = 5;

    @Override
    @Nullable
    public Map<String, Integer> getCommandsMap() {
        return MapBuilder.of(
                "animateToRegion", ANIMATE_TO_REGION,
                "animateToCoordinate", ANIMATE_TO_COORDINATE,
                "fitToElements", FIT_TO_ELEMENTS,
                "fitToSuppliedMarkers", FIT_TO_SUPPLIED_MARKERS,
                "fitToCoordinates", FIT_TO_COORDINATES
        );
    }

    @Override
    public void receiveCommand(T view, int commandId, @Nullable ReadableArray args) {
        Integer duration;
        Double lat;
        Double lng;
        Double lngDelta;
        Double latDelta;
        ReadableMap region;

        switch (commandId) {
            case ANIMATE_TO_REGION:
                region = args.getMap(0);
                duration = args.getInt(1);
                lng = region.getDouble("longitude");
                lat = region.getDouble("latitude");
                lngDelta = region.getDouble("longitudeDelta");
                latDelta = region.getDouble("latitudeDelta");
                SimpleBounds bounds = new SimpleBounds(
                        new SimpleLatLng(lat - latDelta / 2, lng - lngDelta / 2), // southwest
                        new SimpleLatLng(lat + latDelta / 2, lng + lngDelta / 2)  // northeast
                );
                view.animateToRegion(bounds, duration);
                break;

            case ANIMATE_TO_COORDINATE:
                region = args.getMap(0);
                duration = args.getInt(1);
                lng = region.getDouble("longitude");
                lat = region.getDouble("latitude");
                view.animateToCoordinate(new SimpleLatLng(lat, lng), duration);
                break;

            case FIT_TO_ELEMENTS:
                view.fitToElements(args.getBoolean(0));
                break;

            case FIT_TO_SUPPLIED_MARKERS:
                ReadableArray array = args.getArray(0);
                List<String> markerIds = new ArrayList<>();
                for (int i = 0; i < array.size(); i++) {
                    markerIds.add(array.getString(i));
                }
                view.fitToSuppliedMarkers(markerIds, args.getBoolean(1));
                break;
            case FIT_TO_COORDINATES:
                ReadableArray coordsArray = args.getArray(0);
                ReadableMap paddings = args.getMap(1);
                List<SimpleLatLng> coords = new ArrayList<>();
                for (int i = 0; i < coordsArray.size(); i++) {
                    ReadableMap latLng = coordsArray.getMap(i);
                    coords.add(new SimpleLatLng(latLng.getDouble("latitude"), latLng.getDouble("longitude")));
                }

                if (paddings == null) {
                    view.fitToCoordinates(coords, 0, 0, 0, 0, args.getBoolean(2));
                } else {
                    int left = paddings.getInt("left");
                    int top = paddings.getInt("top");
                    int right = paddings.getInt("right");
                    int bottom = paddings.getInt("bottom");

                    view.fitToCoordinates(coords, left, top, right, bottom, args.getBoolean(2));
                }
                break;
        }
    }

    @Override
    @Nullable
    public Map getExportedCustomDirectEventTypeConstants() {
        Map<String, Map<String, String>> map = MapBuilder.of(
                "onMapReady", MapBuilder.of("registrationName", "onMapReady"),
                "onPress", MapBuilder.of("registrationName", "onPress"),
                "onLongPress", MapBuilder.of("registrationName", "onLongPress"),
                "onMarkerPress", MapBuilder.of("registrationName", "onMarkerPress"),
                "onMarkerSelect", MapBuilder.of("registrationName", "onMarkerSelect"),
                "onMarkerDeselect", MapBuilder.of("registrationName", "onMarkerDeselect"),
                "onCalloutPress", MapBuilder.of("registrationName", "onCalloutPress")
        );

        map.putAll(MapBuilder.of(
                "onMarkerDragStart", MapBuilder.of("registrationName", "onMarkerDragStart"),
                "onMarkerDrag", MapBuilder.of("registrationName", "onMarkerDrag"),
                "onMarkerDragEnd", MapBuilder.of("registrationName", "onMarkerDragEnd"),
                "onPanDrag", MapBuilder.of("registrationName", "onPanDrag")
        ));

        return map;
    }

    @Override
    public LayoutShadowNode createShadowNodeInstance() {
        // A custom shadow node is needed in order to pass back the width/height of the map to the
        // view manager so that it can start applying camera moves with bounds.
        return new SizeReportingShadowNode();
    }

}

@@ -3160,63 +3160,8 @@
 0);%0A
-                ReadableMap paddings = args.getMap(1);%0A
     
@@ -3500,24 +3500,22 @@
 if (
-paddings == null
+args.isNull(1)
 ) %7B%0A
@@ -3622,16 +3622,75 @@
  else %7B%0A
+                    ReadableMap paddings = args.getMap(1);%0A
         

fix bug when fit to coordinates padding is null