#import "BarcodeScannerView.h"
#import <AVFoundation/AVFoundation.h>
#import <react/renderer/components/RNBarcodeScannerViewSpec/ComponentDescriptors.h>
#import <react/renderer/components/RNBarcodeScannerViewSpec/EventEmitters.h>
#import <react/renderer/components/RNBarcodeScannerViewSpec/Props.h>
#import <react/renderer/components/RNBarcodeScannerViewSpec/RCTComponentViewHelpers.h>
#import "RCTFabricComponentsPlugins.h"
#import <UIKit/UIKit.h>
#import <react_native_barcode_scanner-Swift.h>

using namespace facebook::react;

@interface BarcodeScannerView () <RCTBarcodeScannerViewViewProtocol, SwiftBarcodeScannerViewDelegate>
@end

@implementation BarcodeScannerView {
    UIView * _view;
    AVCaptureDevice* videoDevice;
    NSString* previouslyScannedCode;
    NSString* previouslyScannedCodeType;
    SwiftBarcodeScannerView *swiftView;
}
+ (ComponentDescriptorProvider)componentDescriptorProvider
{
    return concreteComponentDescriptorProvider<BarcodeScannerViewComponentDescriptor>();
}
- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        static const auto defaultProps = std::make_shared<const BarcodeScannerViewProps>();
        _props = defaultProps;
        _view = [[UIView alloc] init];

        videoDevice = [AVCaptureDevice defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInWideAngleCamera
                                                         mediaType:AVMediaTypeVideo
                                                          position:AVCaptureDevicePositionBack];
        [videoDevice lockForConfiguration:NULL];
        
        const auto &newViewProps = *std::static_pointer_cast<BarcodeScannerViewProps const>(_props);
        
        self.contentView = [[UIView alloc] init];
        
        NSMutableArray<NSString*>* acceptedFormats = [[NSMutableArray alloc] init];
        for (auto it = begin (newViewProps.acceptFormats.acceptedFormats); it != end (newViewProps.acceptFormats.acceptedFormats); ++it) {
            [acceptedFormats addObject:[NSString stringWithUTF8String:it->c_str()]];
        }
                
        swiftView = [[SwiftBarcodeScannerView alloc] initWithFocusWidth:[NSNumber numberWithInt:newViewProps.frameWidth]
                                                            focusHeight:[NSNumber numberWithInt:newViewProps.frameHeight]
                                                       focusBorderColor:[[NSString alloc] initWithCString:newViewProps.frameBorderColor.c_str() encoding:NSUTF8StringEncoding]
                                                       flashModeEnabled:newViewProps.flashModeEnabled
                                                        acceptedFormats:acceptedFormats
        ];
        [swiftView setTranslatesAutoresizingMaskIntoConstraints:NO];
        [swiftView setDelegate:self];
        
        [self.contentView addSubview:swiftView];
        swiftView.layer.bounds = self.contentView.frame;
        [NSLayoutConstraint activateConstraints:@[
            [swiftView.centerXAnchor constraintEqualToAnchor:self.contentView.centerXAnchor],
            [swiftView.centerYAnchor constraintEqualToAnchor:self.contentView.centerYAnchor],
            [swiftView.widthAnchor constraintEqualToAnchor:self.contentView.widthAnchor],
            [swiftView.heightAnchor constraintEqualToAnchor:self.contentView.heightAnchor],
        ]];
        
    }
    return self;
}

- (void)swiftBarcodeScannerView:(SwiftBarcodeScannerView *)swiftBarcodeScannerView didScanCode:(NSString *)code {
    const auto eventEmitter = [self getEventEmitter];

    if (eventEmitter) {
        eventEmitter->onScanResultListener(BarcodeScannerViewEventEmitter::OnScanResultListener{
            .value = [code cStringUsingEncoding:NSUTF8StringEncoding]
        });
    }
}

- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
{
    const auto &newViewProps = *std::static_pointer_cast<BarcodeScannerViewProps const>(props);
    
    NSMutableArray<NSString*>* acceptedFormats = [[NSMutableArray alloc] init];
    for (auto it = begin (newViewProps.acceptFormats.acceptedFormats); it != end (newViewProps.acceptFormats.acceptedFormats); ++it) {
        [acceptedFormats addObject:[NSString stringWithUTF8String:it->c_str()]];
    }
    [swiftView updateWithFocusWidth:[NSNumber numberWithInt:newViewProps.frameWidth]
                        focusHeight:[NSNumber numberWithInt:newViewProps.frameHeight]
                   focusBorderColor:[[NSString alloc] initWithCString:newViewProps.frameBorderColor.c_str() encoding:NSUTF8StringEncoding]
                   flashModeEnabled:newViewProps.flashModeEnabled
                    acceptedFormats:acceptedFormats];
    
    [super updateProps:props oldProps:oldProps];
}

- (std::shared_ptr<const BarcodeScannerViewEventEmitter>)getEventEmitter
{
    if (!self->_eventEmitter) {
      return nullptr;
    }
    assert(std::dynamic_pointer_cast<BarcodeScannerViewEventEmitter const>(self->_eventEmitter));
    return std::static_pointer_cast<BarcodeScannerViewEventEmitter const>(self->_eventEmitter);
}
Class<RCTComponentViewProtocol> BarcodeScannerViewCls(void)
{
    return BarcodeScannerView.class;
}
@end

