//
//  PhobosUtil.m
//  Pods
//
//  Created by Thierry on 16/2/15.
//
//

#import "PhobosUtil.h"
#import <zlib.h>
#import "PhobosConfig.h"
#import "WMCacheService.h"

@implementation PhobosUtil

+ (NSData *)compressData:(NSData *)originData{
    if (!originData || [originData length] == 0)
    {
        return nil;
    }
    
    z_stream zlibStreamStruct;
    zlibStreamStruct.zalloc    = Z_NULL; // Set zalloc, zfree, and opaque to Z_NULL so
    zlibStreamStruct.zfree     = Z_NULL; // that when we call deflateInit2 they will be
    zlibStreamStruct.opaque    = Z_NULL; // updated to use default allocation functions.
    zlibStreamStruct.total_out = 0; // Total number of output bytes produced so far
    zlibStreamStruct.next_in   = (Bytef*)[originData bytes]; // Pointer to input bytes
    zlibStreamStruct.avail_in  = (uInt)[originData length]; // Number of input bytes left to process
    
    int initError = deflateInit2(&zlibStreamStruct, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY);
    if (initError != Z_OK)
    {
        NSString *errorMsg = nil;
        switch (initError)
        {
            case Z_STREAM_ERROR:
                errorMsg = @"Invalid parameter passed in to function.";
                break;
            case Z_MEM_ERROR:
                errorMsg = @"Insufficient memory.";
                break;
            case Z_VERSION_ERROR:
                errorMsg = @"The version of zlib.h and the version of the library linked do not match.";
                break;
            default:
                errorMsg = @"Unknown error code.";
                break;
        }
        return nil;
    }
    NSMutableData *compressedData = [NSMutableData dataWithLength:[originData length] * 1.01 + 12];
    NSInteger deflateStatus;
    do
    {
        zlibStreamStruct.next_out = [compressedData mutableBytes] + zlibStreamStruct.total_out;
        zlibStreamStruct.avail_out = (uInt)([compressedData length] - zlibStreamStruct.total_out);
        deflateStatus = deflate(&zlibStreamStruct, Z_FINISH);
        
    } while ( deflateStatus == Z_OK );
    
    // Check for zlib error and convert code to usable error message if appropriate
    if (deflateStatus != Z_STREAM_END)
    {
        NSString *errorMsg = nil;
        switch (deflateStatus)
        {
            case Z_ERRNO:
                errorMsg = @"Error occured while reading file.";
                break;
            case Z_STREAM_ERROR:
                errorMsg = @"The stream state was inconsistent (e.g., next_in or next_out was NULL).";
                break;
            case Z_DATA_ERROR:
                errorMsg = @"The deflate data was invalid or incomplete.";
                break;
            case Z_MEM_ERROR:
                errorMsg = @"Memory could not be allocated for processing.";
                break;
            case Z_BUF_ERROR:
                errorMsg = @"Ran out of output buffer for writing compressed bytes.";
                break;
            case Z_VERSION_ERROR:
                errorMsg = @"The version of zlib.h and the version of the library linked do not match.";
                break;
            default:
                errorMsg = @"Unknown error code.";
                break;
        }
        deflateEnd(&zlibStreamStruct);
        return nil;
    }
    deflateEnd(&zlibStreamStruct);
    [compressedData setLength: zlibStreamStruct.total_out];
    phobosLog([NSString stringWithFormat:@"Compressed file from %lu B to %lu B", [originData length], [compressedData length]]);
    return compressedData;
}

+ (void)sendData:(NSData *)data success:(SendDataSuccessBlock)success {
#ifdef DEBUG
    NSString *url = @"http://log.test.gengmei.cc/log/collect";
#else
    NSString *url = @"http://log.gengmei.cc/log/collect";
#endif
    @try {
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
        [request setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];
        request.HTTPBody = data;
        request.HTTPMethod = @"POST";
        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
            NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
            NSInteger code = res.statusCode;
            if (code == 200) {
                if (success) {
                    success(code);
                }
            }
        }];
    }
    @catch (NSException *exception) {
        phobosLog(exception);
    }
}

@end