#import <React/RCTConvert.h>
#import "RNZoomVideoSdk.h"
#import "RNZoomVideoSdkAnnotationHelper.h"
#import "RCTConvert+RNZoomVideoSdk.h"
#import "RNZoomView.h"

@implementation RNZoomVideoSdkAnnotationHelper

ZoomVideoSDKAnnotationHelper *annotationHelper;

- (ZoomVideoSDKAnnotationHelper *)getAnnotationHelper
{
    @try {
        if (annotationHelper == nil) {
            NSException *e = [NSException exceptionWithName:@"NoAnnotationHelperFound" reason:@"No Annotation Helper Found" userInfo:nil];
            @throw e;
        }
    } @catch (NSException *e) {
        NSLog(@"%@ - %@", e.name, e.reason);
    }
    return annotationHelper;
}

- (void) setAnnotationHelper: (ZoomVideoSDKAnnotationHelper*) helper {
    annotationHelper = helper;
}

- (NSString *) hexStringFromColor:(UIColor *)color {
    if (color == nil) return @"null";

    const CGFloat *components = CGColorGetComponents(color.CGColor);

    CGFloat r = components[0];
    CGFloat g = components[1];
    CGFloat b = components[2];

    return [NSString stringWithFormat:@"#%02lX%02lX%02lX",
            lroundf(r * 255),
            lroundf(g * 255),
            lroundf(b * 255)];
}

- (UIColor *) colorWithHexString: (NSString *) hexString {
    if (hexString == nil | hexString.length < 1) {
        NSException *e = [NSException exceptionWithName:@"Invalid color value" reason:@"Color value is invalid.  It should be a hex value of the form #RGB, #ARGB, #RRGGBB, or #AARRGGBB" userInfo:nil];
        @throw e;
    }
    NSString *colorString = [[hexString stringByReplacingOccurrencesOfString: @"#" withString: @""] uppercaseString];
    CGFloat alpha, red, blue, green;
    switch ([colorString length]) {
        case 3: // #RGB
            alpha = 1.0f;
            red   = [self colorComponentFrom: colorString start: 0 length: 1];
            green = [self colorComponentFrom: colorString start: 1 length: 1];
            blue  = [self colorComponentFrom: colorString start: 2 length: 1];
            break;
        case 4: // #ARGB
            alpha = [self colorComponentFrom: colorString start: 0 length: 1];
            red   = [self colorComponentFrom: colorString start: 1 length: 1];
            green = [self colorComponentFrom: colorString start: 2 length: 1];
            blue  = [self colorComponentFrom: colorString start: 3 length: 1];
            break;
        case 6: // #RRGGBB
            alpha = 1.0f;
            red   = [self colorComponentFrom: colorString start: 0 length: 2];
            green = [self colorComponentFrom: colorString start: 2 length: 2];
            blue  = [self colorComponentFrom: colorString start: 4 length: 2];
            break;
        case 8: // #AARRGGBB
            alpha = [self colorComponentFrom: colorString start: 0 length: 2];
            red   = [self colorComponentFrom: colorString start: 2 length: 2];
            green = [self colorComponentFrom: colorString start: 4 length: 2];
            blue  = [self colorComponentFrom: colorString start: 6 length: 2];
            break;
        default:
            [NSException raise:@"Invalid color value" format: @"Color value %@ is invalid.  It should be a hex value of the form #RBG, #ARGB, #RRGGBB, or #AARRGGBB", hexString];
            break;
    }
    return [UIColor colorWithRed: red green: green blue: blue alpha: alpha];
}

- (CGFloat) colorComponentFrom: (NSString *) string start: (NSUInteger) start length: (NSUInteger) length {
    NSString *substring = [string substringWithRange: NSMakeRange(start, length)];
    NSString *fullHex = length == 2 ? substring : [NSString stringWithFormat: @"%@%@", substring, substring];
    int hexComponent;
    [[NSScanner scannerWithString: fullHex] scanHexInt: &hexComponent];
    return hexComponent / 255.0;
}

RCT_EXPORT_MODULE()


RCT_EXPORT_METHOD(startAnnotation:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject)
{
    dispatch_async(dispatch_get_main_queue(), ^{
        resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @([[self getAnnotationHelper] startAnnotation])]);
    });
}

RCT_EXPORT_METHOD(stopAnnotation:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject)
{
    dispatch_async(dispatch_get_main_queue(), ^{
        resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @([[self getAnnotationHelper] stopAnnotation])]);
    });
}

RCT_EXPORT_METHOD(setToolColor:(NSString *)toolColor
                  withResolve:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject)
{
    dispatch_async(dispatch_get_main_queue(), ^{
        resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @([[self getAnnotationHelper] setToolColor:[self colorWithHexString:toolColor]])]);
    });
}

RCT_EXPORT_METHOD(getToolColor:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject)
{
    dispatch_async(dispatch_get_main_queue(), ^{
        UIColor* color = [[self getAnnotationHelper] getToolColor];
        if (color == nil) {
            resolve(@"null");
        } else {
            resolve([self hexStringFromColor:[[self getAnnotationHelper] getToolColor]]);
        }
    });
}

RCT_EXPORT_METHOD(setToolType:(NSString *)toolType
                  withResolve:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject)
{
    dispatch_async(dispatch_get_main_queue(), ^{
        resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @([[self getAnnotationHelper] setToolType:[RCTConvert ZoomVideoSDKAnnotationToolType:toolType]])]);
    });
}

RCT_EXPORT_METHOD(getToolType:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject)
{
    dispatch_async(dispatch_get_main_queue(), ^{
        resolve([[RCTConvert ZoomVideoSDKAnnotationToolTypeValuesReversed] objectForKey: @([[self getAnnotationHelper] getToolType])]);
    });
}

RCT_EXPORT_METHOD(setToolWidth:(NSUInteger)width
                  withResolve:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject)
{
    dispatch_async(dispatch_get_main_queue(), ^{
        resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @([[self getAnnotationHelper] setToolWidth:width])]);
    });
}

RCT_EXPORT_METHOD(getToolWidth:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject)
{
    dispatch_async(dispatch_get_main_queue(), ^{
        resolve(@([[self getAnnotationHelper] getToolWidth]));
    });
}

RCT_EXPORT_METHOD(undo:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject)
{
    dispatch_async(dispatch_get_main_queue(), ^{
        resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @([[self getAnnotationHelper] undo])]);
    });
}

RCT_EXPORT_METHOD(redo:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject)
{
    dispatch_async(dispatch_get_main_queue(), ^{
        resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @([[self getAnnotationHelper] redo])]);
    });
}

RCT_EXPORT_METHOD(clear:(NSString *)clearType
                  withResolve:(RCTPromiseResolveBlock)resolve
                  withRejecter:(RCTPromiseRejectBlock)reject)
{
    dispatch_async(dispatch_get_main_queue(), ^{
        resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @([[self getAnnotationHelper] clear:[RCTConvert ZoomVideoSDKAnnotationClearType:clearType]])]);
    });
}

RCT_EXPORT_METHOD(canDoAnnotation:(RCTPromiseResolveBlock)resolve
        withRejecter:(RCTPromiseRejectBlock)reject)
{
    resolve(@([[self getAnnotationHelper] canDoAnnotation]));
}

@end
