// NetworkManager.mm
#import "NetworkManager.h"
#import <Network/Network.h>

@interface NetworkManager()

@property (nonatomic, strong) nw_path_monitor_t monitor;
@property (nonatomic, assign) BOOL connected;

@end

@implementation NetworkManager

+ (instancetype)sharedManager {
    static NetworkManager *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[NetworkManager alloc] initPrivate];
    });
    return instance;
}

// Private init to start monitoring immediately
- (instancetype)initPrivate {
    self = [super init];
    if (self) {
        _connected = NO;
        [self startMonitoring];
    }
    return self;
}

// Prevent use of plain init
- (instancetype)init {
    @throw [NSException exceptionWithName:@"Singleton"
                                   reason:@"Use +[NetworkManager sharedManager]"
                                 userInfo:nil];
    return nil;
}

- (void)startMonitoring {
    if (self.monitor) return; // already monitoring

    self.monitor = nw_path_monitor_create();
    nw_path_monitor_set_queue(self.monitor, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0));

    nw_path_monitor_set_update_handler(self.monitor, ^(nw_path_t path) {

        BOOL hasInternet = (nw_path_get_status(path) == nw_path_status_satisfied);

        // BOOL isWiFi = nw_path_uses_interface_type(path, nw_interface_type_wifi);
        // BOOL isCellular = nw_path_uses_interface_type(path, nw_interface_type_cellular);
        // BOOL isEthernet = nw_path_uses_interface_type(path, nw_interface_type_wired);

        self.connected = hasInternet; 
        // && (isWiFi || isCellular || isEthernet);

        // note that simulator might not report correct status
        NSLog(@"[NetworkManager] Connected = %@", self.connected ? @"YES" : @"NO");

        dispatch_async(dispatch_get_main_queue(), ^{
            [[NSNotificationCenter defaultCenter] postNotificationName:@"NetworkStatusChanged"
                                                                object:nil
                                                              userInfo:@{@"connected": @(self.connected)}];
        });
    });
    nw_path_monitor_start(self.monitor);
}

- (BOOL)isConnected {
    return self.connected;
}

@end
