// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "GoogleMapPolygonController.h"
#import "JsonConversions.h"

@implementation FLTGoogleMapPolygonController {
  GMSPolygon* _polygon;
  GMSMapView* _mapView;
}
- (instancetype)initPolygonWithPath:(GMSMutablePath*)path
                          polygonId:(NSString*)polygonId
                            mapView:(GMSMapView*)mapView {
  self = [super init];
  if (self) {
    _polygon = [GMSPolygon polygonWithPath:path];
    _mapView = mapView;
    _polygonId = polygonId;
    _polygon.userData = @[ polygonId ];
  }
  return self;
}

- (void)removePolygon {
  _polygon.map = nil;
}

#pragma mark - FLTGoogleMapPolygonOptionsSink methods

- (void)setConsumeTapEvents:(BOOL)consumes {
  _polygon.tappable = consumes;
}
- (void)setVisible:(BOOL)visible {
  _polygon.map = visible ? _mapView : nil;
}
- (void)setZIndex:(int)zIndex {
  _polygon.zIndex = zIndex;
}
- (void)setPoints:(NSArray<CLLocation*>*)points {
  GMSMutablePath* path = [GMSMutablePath path];

  for (CLLocation* location in points) {
    [path addCoordinate:location.coordinate];
  }
  _polygon.path = path;
}
- (void)setHoles:(NSArray<NSArray<CLLocation*>*>*)rawHoles {
  NSMutableArray<GMSMutablePath*>* holes = [[NSMutableArray<GMSMutablePath*> alloc] init];

  for (NSArray<CLLocation*>* points in rawHoles) {
    GMSMutablePath* path = [GMSMutablePath path];
    for (CLLocation* location in points) {
      [path addCoordinate:location.coordinate];
    }
    [holes addObject:path];
  }

  _polygon.holes = holes;
}

- (void)setFillColor:(UIColor*)color {
  _polygon.fillColor = color;
}
- (void)setStrokeColor:(UIColor*)color {
  _polygon.strokeColor = color;
}
- (void)setStrokeWidth:(CGFloat)width {
  _polygon.strokeWidth = width;
}
@end

static int ToInt(NSNumber* data) { return [FLTGoogleMapJsonConversions toInt:data]; }

static BOOL ToBool(NSNumber* data) { return [FLTGoogleMapJsonConversions toBool:data]; }

static NSArray<CLLocation*>* ToPoints(NSArray* data) {
  return [FLTGoogleMapJsonConversions toPoints:data];
}

static NSArray<NSArray<CLLocation*>*>* ToHoles(NSArray<NSArray*>* data) {
  return [FLTGoogleMapJsonConversions toHoles:data];
}

static UIColor* ToColor(NSNumber* data) { return [FLTGoogleMapJsonConversions toColor:data]; }

static void InterpretPolygonOptions(NSDictionary* data, id<FLTGoogleMapPolygonOptionsSink> sink,
                                    NSObject<FlutterPluginRegistrar>* registrar) {
  NSNumber* consumeTapEvents = data[@"consumeTapEvents"];
  if (consumeTapEvents != nil) {
    [sink setConsumeTapEvents:ToBool(consumeTapEvents)];
  }

  NSNumber* visible = data[@"visible"];
  if (visible != nil) {
    [sink setVisible:ToBool(visible)];
  }

  NSNumber* zIndex = data[@"zIndex"];
  if (zIndex != nil) {
    [sink setZIndex:ToInt(zIndex)];
  }

  NSArray* points = data[@"points"];
  if (points) {
    [sink setPoints:ToPoints(points)];
  }

  NSArray* holes = data[@"holes"];
  if (holes) {
    [sink setHoles:ToHoles(holes)];
  }

  NSNumber* fillColor = data[@"fillColor"];
  if (fillColor != nil) {
    [sink setFillColor:ToColor(fillColor)];
  }

  NSNumber* strokeColor = data[@"strokeColor"];
  if (strokeColor != nil) {
    [sink setStrokeColor:ToColor(strokeColor)];
  }

  NSNumber* strokeWidth = data[@"strokeWidth"];
  if (strokeWidth != nil) {
    [sink setStrokeWidth:ToInt(strokeWidth)];
  }
}

@implementation FLTPolygonsController {
  NSMutableDictionary* _polygonIdToController;
  FlutterMethodChannel* _methodChannel;
  NSObject<FlutterPluginRegistrar>* _registrar;
  GMSMapView* _mapView;
}
- (instancetype)init:(FlutterMethodChannel*)methodChannel
             mapView:(GMSMapView*)mapView
           registrar:(NSObject<FlutterPluginRegistrar>*)registrar {
  self = [super init];
  if (self) {
    _methodChannel = methodChannel;
    _mapView = mapView;
    _polygonIdToController = [NSMutableDictionary dictionaryWithCapacity:1];
    _registrar = registrar;
  }
  return self;
}
- (void)addPolygons:(NSArray*)polygonsToAdd {
  for (NSDictionary* polygon in polygonsToAdd) {
    GMSMutablePath* path = [FLTPolygonsController getPath:polygon];
    NSString* polygonId = [FLTPolygonsController getPolygonId:polygon];
    FLTGoogleMapPolygonController* controller =
        [[FLTGoogleMapPolygonController alloc] initPolygonWithPath:path
                                                         polygonId:polygonId
                                                           mapView:_mapView];
    InterpretPolygonOptions(polygon, controller, _registrar);
    _polygonIdToController[polygonId] = controller;
  }
}
- (void)changePolygons:(NSArray*)polygonsToChange {
  for (NSDictionary* polygon in polygonsToChange) {
    NSString* polygonId = [FLTPolygonsController getPolygonId:polygon];
    FLTGoogleMapPolygonController* controller = _polygonIdToController[polygonId];
    if (!controller) {
      continue;
    }
    InterpretPolygonOptions(polygon, controller, _registrar);
  }
}
- (void)removePolygonIds:(NSArray*)polygonIdsToRemove {
  for (NSString* polygonId in polygonIdsToRemove) {
    if (!polygonId) {
      continue;
    }
    FLTGoogleMapPolygonController* controller = _polygonIdToController[polygonId];
    if (!controller) {
      continue;
    }
    [controller removePolygon];
    [_polygonIdToController removeObjectForKey:polygonId];
  }
}
- (void)onPolygonTap:(NSString*)polygonId {
  if (!polygonId) {
    return;
  }
  FLTGoogleMapPolygonController* controller = _polygonIdToController[polygonId];
  if (!controller) {
    return;
  }
  [_methodChannel invokeMethod:@"polygon#onTap" arguments:@{@"polygonId" : polygonId}];
}
- (bool)hasPolygonWithId:(NSString*)polygonId {
  if (!polygonId) {
    return false;
  }
  return _polygonIdToController[polygonId] != nil;
}
+ (GMSMutablePath*)getPath:(NSDictionary*)polygon {
  NSArray* pointArray = polygon[@"points"];
  NSArray<CLLocation*>* points = ToPoints(pointArray);
  GMSMutablePath* path = [GMSMutablePath path];
  for (CLLocation* location in points) {
    [path addCoordinate:location.coordinate];
  }
  return path;
}
+ (NSString*)getPolygonId:(NSDictionary*)polygon {
  return polygon[@"polygonId"];
}
@end
