//
//  XSHelper.m
//  nochange
//
//  Created by mac on 2024/10/15.
//

#import <Foundation/Foundation.h>
#import "XSHelper.h"



NSError* XSErrorFromException(NSException* exception) {
    NSMutableDictionary* userInfo = [NSMutableDictionary dictionary];
    
    [userInfo setObject:exception.name forKey:NSLocalizedFailureReasonErrorKey];
    [userInfo setObject:exception.reason forKey:NSLocalizedDescriptionKey];
    
    if (exception.userInfo) {
        [userInfo addEntriesFromDictionary:exception.userInfo];
    }
    
    return [NSError errorWithDomain:@"ExceptionDomain" code:-1 userInfo:userInfo];
}

// mach_absolute_time()
double XSCalculateElapsedTime(uint64_t start, uint64_t end) {
    static mach_timebase_info_data_t timebaseInfo;
    if (timebaseInfo.denom == 0) {
        mach_timebase_info(&timebaseInfo);
    }
    
    uint64_t elapsed = end - start;
    uint64_t nanos = elapsed * timebaseInfo.numer / timebaseInfo.denom;
    return (double)nanos / NSEC_PER_MSEC;
}
// 小数位保留
float XSRoundToDecimal(float value, int decimalPlaces) {
    float multiplier = powf(10.0f, decimalPlaces);
    return roundf(value * multiplier) / multiplier;
}

void XSAfterNext(int sec, NextCallback next) {
    // 或使用GCD timer
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, sec * NSEC_PER_SEC, 0);
    dispatch_source_set_event_handler(timer, ^{
        // 延迟操作
        next();
    });
    dispatch_resume(timer);
}



@interface XSHelper()
{
    
}

@end


@implementation XSHelper

+ (int)random:(int)min and:(int)max {
    return min + arc4random_uniform(max - min + 1);
}

+ (NSData *)str2Data:(NSString *)str {
    return [str dataUsingEncoding:NSUTF8StringEncoding];
}
+ (NSString *)data2str: (NSData *) data {
    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];;
}
+ (BOOL) strIsEmpty: (NSString *)str {
    if (str == nil) {
        return YES;
    }
    if ([str isEqual:[NSNull null]]) {
        return YES;
    }
    if ([str length] <=0) {
        return YES;
    }
    return NO;
}
+ (bool) isMatch: (NSString *)pattern test:(NSString *)test {
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
                                                                           options:0
                                                                             error:nil];
    NSUInteger numberOfMatches = [regex numberOfMatchesInString:test
                                                        options:0
                                                          range:NSMakeRange(0, [test length])];
    return numberOfMatches > 0;
}

+ (NSDictionary *) json2Dictionary: (NSString *)json {
    if(json == nil || [json isEqual:[NSNull null]] || [json isEqual:@""]) {
        return @{};
    }
    return [XSHelper jsonData2Dictionary:[XSHelper str2Data:json]];
}

+ (NSDictionary *) jsonData2Dictionary: (NSData *)data {
    NSError *jsonError;
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data
                                          options:NSJSONReadingMutableContainers
                                            error:&jsonError];
    if (jsonError) {
        NSLog(@"json2dic error: %@", jsonError);
    }
    return dic;
}
+ (NSData *)obj2JsonData:(id)obj {
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:obj
                                                       options:NSJSONWritingPrettyPrinted
                                                         error:&error];

    return jsonData;
}

+ (NSString *)dic2Json: (NSDictionary *)dict {
    NSData *jsonData = [XSHelper obj2JsonData:dict];
    return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}

+ (NSString *)readFileText:(NSString *)path {
    NSError *error = nil;
    NSString *content = [NSString stringWithContentsOfFile:path
                                                  encoding:NSUTF8StringEncoding
                                                     error:&error];
    if (error) {
        NSLog(@"XS- Helper readFileText Error: %@", error.localizedDescription);
        return nil;
    }
    return content;
}
+ (BOOL) saveFile: (NSString *) path data: (NSData *)data {
    return [data writeToFile:path atomically:YES];
}

+ (BOOL) saveFile: (NSString *) path text: (NSString *)text {
    NSData *data = [XSHelper str2Data:text];
    return [XSHelper saveFile:path data:data];
}

+ (void) rmFiles: (NSString *) path {
    NSFileManager *man = [NSFileManager defaultManager];
    if ([man fileExistsAtPath:path]) {
        NSArray *dirArray = [man contentsOfDirectoryAtPath:path error:nil];
        for (NSString * str in dirArray) {
            NSString *subPath  = [path stringByAppendingPathComponent:str];
            NSLog(@"XS- del file:%@", subPath);
            NSError *error;
            [man removeItemAtPath:subPath error:&error];
            if (error) {
                NSLog(@"XS- Error clearing: %@,,%@", path, error.localizedDescription);
            }
        }
    } else {
        NSLog(@"XS- %@ not found", path);
    }
    
}

+ (NSNumber *)str2num:(NSString *)str {
    NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
    f.numberStyle = NSNumberFormatterDecimalStyle;
    NSNumber *myNumber = [f numberFromString:str];
    return myNumber;
}
+ (NSString *)replaceStr: (NSString *)text oldStr:(NSString *)oldStr newStr: (NSString *)newStr {
    return [text stringByReplacingOccurrencesOfString:oldStr withString:newStr];
}

+ (void)replaceMulStr: (NSMutableString *)text  oldStr:(NSString *)oldStr newStr: (NSString *)newStr {
    [text replaceOccurrencesOfString:oldStr
                                   withString:newStr
                                      options:NSLiteralSearch
                                        range:NSMakeRange(0, [text length])];
}

+ (NSString *)replaceStr: (NSString *)text regex:(NSString *)regex newStr:(NSString *)newStr {
    NSError *error = nil;
    NSRegularExpression *nsregex = [NSRegularExpression regularExpressionWithPattern:regex
                                                                           options:0
                                                                             error:&error];
    if (!error) {
        NSString *newString = [nsregex stringByReplacingMatchesInString:text
                                                              options:0
                                                                range:NSMakeRange(0, [text length])
                                                         withTemplate:@"YYYY-MM-DD"];
        NSLog(@"%@", newString); // 输出: The date is YYYY-MM-DD
        return newString;
    }
    return text;
}

///  编码：A => QQ==
+ (NSString *)base64Encode:(NSString *)string {
    // 1. 将字符串转换成二进制数据
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
   
    // 2. 利用 iOS 7.0 的方法，直接 base64 编码
    return [data base64EncodedStringWithOptions:0];
}
 
///  解码：QQ== => A
+ (NSString *)base64Decode:(NSString *)string {
    // 1. 将base64编码后的字符串，解码成二进制数据
    NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:0];
   
    // 2. 返回解码后的字符串
    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}

//-- img
+ (UIImage *) imageFromFile:(NSString *) path {
    return [UIImage imageWithContentsOfFile:path];
}
+ (NSString *)base64StringFromJpgImage:(UIImage *)image {
    NSData *imageData = UIImageJPEGRepresentation(image, 0.8);
    NSString *base64String = [imageData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
    return base64String;
}

+  (UIImage *)imageFromBase64String:(NSString *)base64String {
    NSData *imageData = [[NSData alloc] initWithBase64EncodedString:base64String options:NSDataBase64DecodingIgnoreUnknownCharacters];
    return [UIImage imageWithData:imageData];
}
+ (UIImage *)png2jpg:(UIImage *)png {
    NSData *jpgdata = UIImageJPEGRepresentation(png, 0.8);
    return [UIImage imageWithData:jpgdata];
}




+ (double) getCurTime {
    // 获取当前日期和时间
    NSDate *now = [NSDate date];
    return [now timeIntervalSince1970];
}


// Vision
+ (void)performOCROnImage:(UIImage *)image callback:(MyOCRCallback)callback {
    NSLog(@"XS- performOCROnImage");
    if (!image) {
        NSLog(@"XS- No image provided");
        callback(@"");
        return;
    }
    
    // 在后台队列中执行 OCR
    dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
        // 创建 VNImageRequestHandler
        VNImageRequestHandler *imageRequestHandler = [[VNImageRequestHandler alloc] initWithCIImage:[CIImage imageWithCGImage:image.CGImage]
                                                                                            options:@{}];
        
        // 创建文本识别请求
        VNRecognizeTextRequest *textRecognitionRequest = [[VNRecognizeTextRequest alloc] initWithCompletionHandler:^(VNRequest * _Nonnull request, NSError * _Nullable error) {
            if (error) {
                NSLog(@"XS- Error: %@", error.localizedDescription);
                dispatch_async(dispatch_get_main_queue(), ^{
                    callback(@"");
                });
                return;
            }
            
            NSMutableString *recognizedText = [NSMutableString string];
            for (VNRecognizedTextObservation *observation in request.results) {
                VNRecognizedText *topCandidate = [observation topCandidates:1].firstObject;
                if (topCandidate) {
                    [recognizedText appendFormat:@"%@\n", topCandidate.string];
                }
            }
            
            NSLog(@"XS- Recognized Text:\n%@", recognizedText);
            
            // 在主线程上处理结果
            dispatch_async(dispatch_get_main_queue(), ^{
                callback(recognizedText);
            });
        }];
        
        // 设置识别语言（可选）
        textRecognitionRequest.recognitionLanguages = @[@"en-US", @"zh-Hans"];
        
        // 执行请求
        NSError *error;
        [imageRequestHandler performRequests:@[textRecognitionRequest] error:&error];
        if (error) {
            NSLog(@"XS- Error performing OCR request: %@", error.localizedDescription);
            dispatch_async(dispatch_get_main_queue(), ^{
                callback(@"");
            });
        }
    });
}


@end



@implementation NSData (AES)

- (NSData *)aesEncrypt: (NSString *)key iv:(NSString *)iv {
    return [self AES128operation:kCCEncrypt key:key iv:iv];
}

- (NSData *)aesDecrypt: (NSString *)key iv:(NSString *)iv {
    return [self AES128operation:kCCDecrypt key:key iv:iv];
}

- (NSData *)AES128operation:(CCOperation)operation key:(NSString *)key iv:(NSString *)iv
{
    char keyPtr[kCCKeySizeAES128 + 1];
    bzero(keyPtr, sizeof(keyPtr));
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    
    // IV
    char ivPtr[kCCBlockSizeAES128 + 1];
    bzero(ivPtr, sizeof(ivPtr));
    [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
    
    size_t bufferSize = [self length] + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    size_t numBytesEncrypted = 0;
    
   
    
    CCCryptorStatus cryptorStatus = CCCrypt(operation, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                            keyPtr, kCCKeySizeAES128,
                                            ivPtr,
                                            self.bytes, self.length,
                                            buffer, bufferSize,
                                            &numBytesEncrypted);
    
    if(cryptorStatus == kCCSuccess) {
        NSLog(@"Success");
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    } else {
        NSLog(@"Error");
    }
    
    free(buffer);
    return nil;
}

@end


@implementation NSString (AES)

- (NSString *)aesEncrypt: (NSString *)key iv:(NSString *)iv {
    NSData *data = [[XSHelper str2Data:self] aesEncrypt:key iv:iv];
    return [data base64EncodedStringWithOptions:0];
}

- (NSString *)aesDecrypt: (NSString *)key iv:(NSString *)iv {
    NSData *data = [[NSData alloc] initWithBase64EncodedString:self options:0];
    NSData *dec = [data aesDecrypt:key iv:iv];
    return [XSHelper data2str:dec];
}

@end



