// 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 "FLTGoogleMapTileOverlayController.h"
#import "JsonConversions.h"

static void InterpretTileOverlayOptions(NSDictionary *data,
                                        id<FLTGoogleMapTileOverlayOptionsSink> sink,
                                        NSObject<FlutterPluginRegistrar> *registrar) {
  NSNumber *visible = data[@"visible"];
  if (visible != nil) {
    [sink setVisible:visible.boolValue];
  }

  NSNumber *transparency = data[@"transparency"];
  if (transparency != nil) {
    [sink setTransparency:transparency.floatValue];
  }

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

  NSNumber *fadeIn = data[@"fadeIn"];
  if (fadeIn != nil) {
    [sink setFadeIn:fadeIn.boolValue];
  }

  NSNumber *tileSize = data[@"tileSize"];
  if (tileSize != nil) {
    [sink setTileSize:tileSize.integerValue];
  }
}

@interface FLTGoogleMapTileOverlayController ()

@property(strong, nonatomic) GMSTileLayer *layer;
@property(weak, nonatomic) GMSMapView *mapView;

@end

@implementation FLTGoogleMapTileOverlayController

- (instancetype)initWithTileLayer:(GMSTileLayer *)tileLayer mapView:(GMSMapView *)mapView {
  self = [super init];
  if (self) {
    self.layer = tileLayer;
    self.mapView = mapView;
  }
  return self;
}

- (void)removeTileOverlay {
  self.layer.map = nil;
}

- (void)clearTileCache {
  [self.layer clearTileCache];
}

- (NSDictionary *)getTileOverlayInfo {
  NSMutableDictionary *info = [[NSMutableDictionary alloc] init];
  BOOL visible = self.layer.map != nil;
  info[@"visible"] = @(visible);
  info[@"fadeIn"] = @(self.layer.fadeIn);
  float transparency = 1.0 - self.layer.opacity;
  info[@"transparency"] = @(transparency);
  info[@"zIndex"] = @(self.layer.zIndex);
  return info;
}

#pragma mark - FLTGoogleMapTileOverlayOptionsSink methods

- (void)setFadeIn:(BOOL)fadeIn {
  self.layer.fadeIn = fadeIn;
}

- (void)setTransparency:(float)transparency {
  float opacity = 1.0 - transparency;
  self.layer.opacity = opacity;
}

- (void)setVisible:(BOOL)visible {
  self.layer.map = visible ? self.mapView : nil;
}

- (void)setZIndex:(int)zIndex {
  self.layer.zIndex = zIndex;
}

- (void)setTileSize:(NSInteger)tileSize {
  self.layer.tileSize = tileSize;
}
@end

@interface FLTTileProviderController ()

@property(weak, nonatomic) FlutterMethodChannel *methodChannel;
@property(copy, nonatomic, readwrite) NSString *tileOverlayId;

@end

@implementation FLTTileProviderController

- (instancetype)init:(FlutterMethodChannel *)methodChannel tileOverlayId:(NSString *)tileOverlayId {
  self = [super init];
  if (self) {
    self.methodChannel = methodChannel;
    self.tileOverlayId = tileOverlayId;
  }
  return self;
}

#pragma mark - GMSTileLayer method

- (void)requestTileForX:(NSUInteger)x
                      y:(NSUInteger)y
                   zoom:(NSUInteger)zoom
               receiver:(id<GMSTileReceiver>)receiver {
  [self.methodChannel
      invokeMethod:@"tileOverlay#getTile"
         arguments:@{
           @"tileOverlayId" : self.tileOverlayId,
           @"x" : @(x),
           @"y" : @(y),
           @"zoom" : @(zoom)
         }
            result:^(id _Nullable result) {
              UIImage *tileImage;
              if ([result isKindOfClass:[NSDictionary class]]) {
                FlutterStandardTypedData *typedData = (FlutterStandardTypedData *)result[@"data"];
                if (typedData == nil) {
                  tileImage = kGMSTileLayerNoTile;
                } else {
                  tileImage = [UIImage imageWithData:typedData.data];
                }
              } else {
                if ([result isKindOfClass:[FlutterError class]]) {
                  FlutterError *error = (FlutterError *)result;
                  NSLog(@"Can't get tile: errorCode = %@, errorMessage = %@, details = %@",
                        [error code], [error message], [error details]);
                }
                if ([result isKindOfClass:[FlutterMethodNotImplemented class]]) {
                  NSLog(@"Can't get tile: notImplemented");
                }
                tileImage = kGMSTileLayerNoTile;
              }

              [receiver receiveTileWithX:x y:y zoom:zoom image:tileImage];
            }];
}

@end

@interface FLTTileOverlaysController ()

@property(strong, nonatomic) NSMutableDictionary *tileOverlayIdToController;
@property(weak, nonatomic) FlutterMethodChannel *methodChannel;
@property(weak, nonatomic) NSObject<FlutterPluginRegistrar> *registrar;
@property(weak, nonatomic) GMSMapView *mapView;

@end

@implementation FLTTileOverlaysController

- (instancetype)init:(FlutterMethodChannel *)methodChannel
             mapView:(GMSMapView *)mapView
           registrar:(NSObject<FlutterPluginRegistrar> *)registrar {
  self = [super init];
  if (self) {
    self.methodChannel = methodChannel;
    self.mapView = mapView;
    self.tileOverlayIdToController = [[NSMutableDictionary alloc] init];
    self.registrar = registrar;
  }
  return self;
}

- (void)addTileOverlays:(NSArray *)tileOverlaysToAdd {
  for (NSDictionary *tileOverlay in tileOverlaysToAdd) {
    NSString *tileOverlayId = [FLTTileOverlaysController getTileOverlayId:tileOverlay];
    FLTTileProviderController *tileProvider =
        [[FLTTileProviderController alloc] init:self.methodChannel tileOverlayId:tileOverlayId];
    FLTGoogleMapTileOverlayController *controller =
        [[FLTGoogleMapTileOverlayController alloc] initWithTileLayer:tileProvider
                                                             mapView:self.mapView];
    InterpretTileOverlayOptions(tileOverlay, controller, self.registrar);
    self.tileOverlayIdToController[tileOverlayId] = controller;
  }
}

- (void)changeTileOverlays:(NSArray *)tileOverlaysToChange {
  for (NSDictionary *tileOverlay in tileOverlaysToChange) {
    NSString *tileOverlayId = [FLTTileOverlaysController getTileOverlayId:tileOverlay];
    FLTGoogleMapTileOverlayController *controller = self.tileOverlayIdToController[tileOverlayId];
    if (!controller) {
      continue;
    }
    InterpretTileOverlayOptions(tileOverlay, controller, self.registrar);
  }
}
- (void)removeTileOverlayIds:(NSArray *)tileOverlayIdsToRemove {
  for (NSString *tileOverlayId in tileOverlayIdsToRemove) {
    FLTGoogleMapTileOverlayController *controller = self.tileOverlayIdToController[tileOverlayId];
    if (!controller) {
      continue;
    }
    [controller removeTileOverlay];
    [self.tileOverlayIdToController removeObjectForKey:tileOverlayId];
  }
}

- (void)clearTileCache:(NSString *)tileOverlayId {
  FLTGoogleMapTileOverlayController *controller = self.tileOverlayIdToController[tileOverlayId];
  if (!controller) {
    return;
  }
  [controller clearTileCache];
}

- (nullable NSDictionary *)getTileOverlayInfo:(NSString *)tileverlayId {
  if (self.tileOverlayIdToController[tileverlayId] == nil) {
    return nil;
  }
  return [self.tileOverlayIdToController[tileverlayId] getTileOverlayInfo];
}

+ (NSString *)getTileOverlayId:(NSDictionary *)tileOverlay {
  return tileOverlay[@"tileOverlayId"];
}

@end
