#import <Foundation/Foundation.h>
#import "Bugsee.h"
#import "BugseePluginVersion.h"

id deserialize(const char* string)
{
    if (string) {
        NSError *err = nil;
        NSData *jsonData = [[NSString stringWithUTF8String:string] dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData
                                                             options:NSJSONReadingAllowFragments
                                                               error:&err];
        if (!err && dict) {
            return dict;
        } else {
            return nil;
        }
    } else {
        return nil;
    }
}

const char * serialize(id obj, size_t * size)
{
    if ([obj isKindOfClass:[NSString class]]) {
        NSString * str = [NSString stringWithFormat:@"\"%@\"",obj];
        *size = str.length;
        return str.UTF8String;
    } else if ([obj isKindOfClass:[NSNumber class]]){
        NSString * str = [NSString stringWithFormat:@"%@",obj];
        *size = str.length;
        return str.UTF8String;
    }else{
        NSData * data = [NSJSONSerialization dataWithJSONObject:obj options:0 error:nil];
        NSString * str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        *size = str.length;
        return str.UTF8String;
    }
}

void _bugsee_launch(char *appToken, char* options)
{
    NSMutableDictionary* dict;
    if (options)
        dict = [NSMutableDictionary dictionaryWithDictionary:deserialize(options)];
    else
        dict = [NSMutableDictionary new];

    [dict setObject:@{   @"type"     : @"UNITY",
                         @"version"  : BUGSEE_PLUGIN_VERSION ,
                         @"build"    : BUGSEE_PLUGIN_BUILD   ,
                         @"fps"      : @(UnityGetTargetFPS()),
                         @"metal"    : @(UnitySelectedRenderingAPI() == apiMetal)
                         } forKey:@"wrapper_info"];

    [Bugsee launchWithToken:[NSString stringWithUTF8String:appToken]
                 andOptions:dict];
}

void _bugsee_show_report(char *summary, char *description, int severity)
{
    if (summary) {
        [Bugsee showReportControllerWithSummary:[NSString stringWithUTF8String:summary]
                                    description:[NSString stringWithUTF8String:description]
                                       severity:severity];
    } else {
        [Bugsee showReportController];
    }
}

void _bugsee_pause()
{
    [Bugsee pause];
}

void _bugsee_resume()
{
    [Bugsee resume];
}

void _bugsee_traceKey(char *name, char* wrapperDict)
{
    NSDictionary* dict = deserialize(wrapperDict);
    [Bugsee traceKey:[NSString stringWithUTF8String:name]
           withValue:dict];
}

void _bugsee_registerEvent(char *name, char* params)
{
    if (params)
        [Bugsee registerEvent:[NSString stringWithUTF8String:name]
                   withParams:deserialize(params)];
}

void _bugsee_upload(char *summary, char *description, int severity)
{
    [Bugsee uploadWithSummary:[NSString stringWithUTF8String:summary]
                  description:[NSString stringWithUTF8String:description]
                     severity:severity];

}

void _bugsee_logError(char *description)
{
    NSString * str = [NSString stringWithUTF8String:description];

    [Bugsee logError:[NSError errorWithDomain:@"unity.bugsee.error" code:0 userInfo:@{NSLocalizedDescriptionKey: str?:@""}]];
}

void _bugsee_logException(char *name, char *reason, char *frames, bool handled)
{
    [Bugsee logException:[NSString stringWithUTF8String:name]
                  reason:[NSString stringWithUTF8String:reason]
                  frames:deserialize(frames)
                    type:@"unity"
                 handled:(handled?@(YES):@(NO))];
}

void _bugsee_log(char *message, int level)
{
    BugseeLogLevel lvl = (BugseeLogLevel)level;
    [Bugsee log:[NSString stringWithUTF8String:message] level:lvl];
}

void _bugsee_feedback()
{
    [Bugsee showFeedbackController];
}

void _bugsee_set_def_feedback_greeting(char *message)
{
    [Bugsee setDefaultFeedbackGreeting:[NSString stringWithUTF8String:message]];
}

void _bugsee_assert(bool condition, char *description)
{
    BUGSEE_ASSERT(condition, [NSString stringWithUTF8String:description]);
}

bool _bugsee_set_attribute(char * value)
{
    NSDictionary* dict = deserialize(value);
    if (!dict) return false;
    return [Bugsee setAttribute:dict[@"key"]
                      withValue:dict[@"value"]];
}

const char * _bugsee_get_attribute(char * key)
{
    id attr = [Bugsee getAttribute:[NSString stringWithUTF8String:key]];
    if (!attr) return NULL;
    size_t size;
    const char * result = serialize(attr, &size);

    char * copyResult = malloc(size);
    memcpy((void*)copyResult, result, size);

    return copyResult;
}

bool _bugsee_clear_attribute(char * key)
{
    return [Bugsee clearAttribute:[NSString stringWithUTF8String:key]];
}

void _bugsee_testExceptionCrash()
{
    [Bugsee testExceptionCrash];
}

void _bugsee_testSignalCrash()
{
    [Bugsee testSignalCrash];
}

