//
//  IOSPlatformSDK.m
//  OYGameSKD
//  Created by leon on 2021/1/21.
//  Copyright © 2021 Oujia. All rights reserved.

#import "IOSPlatformSDK.h"
#import "BugTool.h"
#include <sys/signal.h>
#import "MYFactoryManager.h"

#pragma mark ============================>> ios call unity （定义名字参数和C#类一样的方法）
//大概流程就是先将C#的函数指针存入OC内存，在OC需要回调unity的时候就可以使用不同的指针来回调不同的unity方法
/**
*运动数据
* left: 左鞋动作代码
* right: 右鞋动作代码
* 对应 enum CMD_MOTION
*/
typedef void (* MotionHandler) (int cusid, int left, int right);
/**
* 踏步状态，频率
* leftStatus: 左鞋(0:停止, 1:慢,2:快)
* rightStatus: 右鞋(0:停止, 1:慢,2:快)
* leftFrag: 左鞋(每分钟步频)
* rightFrag: 右鞋(每分钟步频)
*/
typedef void (* StepHandler)(int cusid, int leftStatus, int rightStatus, int leftFrag, int rightFrag);
/**
* 返回蓝牙设备的基本信息，用于界面上显示当前的设备状况，app 跳转的时候传过来的
* name: 设备名称
* status: 设备状态 @see enum BLE_STATE
* electricity: 设备电量 取值范围[0 - 100]   对比左右鞋 handler较低的电量
*/
typedef void (* DeviceHandler)(int cusid, const char *name, const char  *address, int status, int electricity);
/**
* 好友列表 unity call ios 异步请求数据后 ios call unity
* 调用api GetUserFriends() 的回调
* code:  请求结果代码 0: 成功， 非0: 根据业务处理
* json: 好友列表数据 , json 数组
*
*/
typedef void (* UserFriendsHandler)(int code, const char * json);

/**
* 调用api GetUserFriends() 的回调
* code:  请求结果代码 0: 成功， 非0: 根据业务处理
* json: 好友列表数据 , json 数组
*/
typedef void (* InviteFriendHandler)(int code, const char * userJson, const char * inviteInfo);//

/**
*游戏首页交互动作的回调
 * cusid: 主副设备
 * code: 交互代码
*/
typedef void (* ActionHandler) (int cusid, int code);

/**
* 游戏榜单数据回调
 * cusid: 主副设备
 * code: 交互代码
*/
typedef void (* GetRankHandler)(int conde,const char * userJson);


/** array: x,y,z姿态数据
* 单位：弧度
* 使用时要将数据 除以 10000
* 转换角度可以使用 Mathf.Rad2Deg
*/
typedef void (* RotateHandler)(int cusid, short lx, short ly, short lz, short rx, short ry, short rz);


/**addGame post 游戏结束后回调给游戏的数据
* json字符串
*/
typedef void (* GameEndResponseHandler)(int code, const char * userJson);

#pragma mark ============================>> 声明 静态指针变量的实例 在unity call ios时候将该指针存储在内存中，在需要ios call unity时，用该指针调用unity的函数接口
static ActionHandler actionHandler;
static MotionHandler motionHandler;
static StepHandler stepHandler;
static DeviceHandler deviceHandler;
static UserFriendsHandler userFriendsHandler;
static InviteFriendHandler inviteFriendHandler;
static GetRankHandler getRankHandler;
static RotateHandler rotateHandler;
static GameEndResponseHandler gameEndResponseHandler;

@implementation IOSPlatformSDK

#pragma mark ============================>> SDK 单例
static IOSPlatformSDK * instance;
+(instancetype)sharedInstance{
     return [[self alloc] init];
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone{
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
      instance = [super allocWithZone:zone];
  });
  return instance;
}

- (instancetype)init{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [super init];
        //初始蓝牙链接
        [BTDataProcess sharedInstance];
        //开始bug监控
        [BugTool startAvoidBug];
    });
    return instance;
}

#pragma mark ============================>> public method app 跳转直链
-(void)startWithUrl:(NSURL*)url{
    [BTDataInstance startWithUrl:url];
}

//
#pragma mark ============================>> private
//是否已经缓存到用户信息
-(BOOL)existUserInfo{
    
    NSDictionary * jsonDict = [IOS_NSUSERDEFAULT objectForKey:IOSSDK_USERINFO];
     if ([jsonDict isKindOfClass:[NSNull class]] || jsonDict == nil || [jsonDict isEqual:[NSNull null]]){
         [PopupView showCusHUDA:@"获取用户信息失败,请从趣动启动"];
         return NO;
     }else{
         return YES;
     }
    
//    UIDevice
    
}

#pragma mark ============================>> ios call unity (数据处理后的回调)
-(void)bridgingMotionAction:(int)cusid
                       left:(int)left
                      right:(int)right{
    if (motionHandler!=nil){
        motionHandler(cusid,left,right);
    }
}

-(void)bridgingStepAction:(int)cusid
               leftStatus:(int)leftStatus
              rightStatus:(int)rightStatus
                 leftFrag:(int)leftFrag
                rightFrag:(int)rightFrag{
    if (stepHandler != nil){
        stepHandler(cusid,leftStatus,rightStatus,leftFrag,rightFrag);
    }
}

-(void)bridgingDeviceAction:(int)cusid
                       name:(NSString*)name
                    address:(NSString*)address
                     status:(int)status
                electricity:(int)electricity{
//        NSLog(@"deviceHandler ===>> %d %@ %@ %d %d",cusid,name,address,status,electricity);
    const char * charName =[name UTF8String];
    const char * charAddress =[address UTF8String];
    if (deviceHandler != nil){
        deviceHandler(cusid,charName,charAddress,status,electricity);
    }
    
}

-(void)bridgingInteraction:(int)cusid
                      code:(int)code{
    //传给unity ---> 旧版游戏未用到
    if (actionHandler != nil){
            actionHandler(cusid,code);
    }
}

-(void)bridgingInvite:(int)code
             userChar:(const char *)userChar
             infoChar:(const char *)infoChar{
        inviteFriendHandler(0,userChar,infoChar);
}

@end

#pragma mark ============================>> unity call ios （声明unity call ios的托管函数 & 接收unity传过来的指针）
/**
 * c语言字符串指针malloc
 */
char* MakeStringCopy(const char* string){
    
    if (string == NULL)
        return NULL;
    char* res = (char*)malloc(strlen(string) + 1);
    strcpy(res, string);
    return res;
    
}

/**
 * unity call ios 主动接收 函数指针
 * MotionHandler 用于ios回调 "蓝牙动作"，在👆🏻bridgingMotionAction中实现
 */
extern "C" {void PointerMotionHandler(MotionHandler  handler){
    motionHandler = handler;
    NSLog(@"PutIntPtr MotionHandler 指针内存地址 ===>> %p",&motionHandler);
    }
}

/**
 * unity call ios 主动接收 函数指针
 * StepHandler 用于ios回调 "鞋子步频"，在👆🏻bridgingStepAction中实现
 */
extern "C" { void PointerStepHandler(StepHandler  handler){
      stepHandler = handler;
    NSLog(@"PutIntPtr StepHandler   指针内存地址 ===>> %p",&stepHandler);
  }
}

/**
 * unity call ios 主动接收 函数指针
 * StepHandler 用于ios回调 "鞋子蓝牙状态和电量"，在👆🏻bridgingDeviceAction中实现
 */
extern "C" {void PointerDeviceHandler(DeviceHandler  handler){
       deviceHandler = handler;
    NSLog(@"PutIntPtr DeviceHandler 指针内存地址 ===>> %p",&deviceHandler);
  }
}

/**
 * unity call ios 主动接收 函数指针
 * ActionHandler 用于ios回调“”蓝牙和游戏大厅交互动作数据”，在👆🏻bridgingMotionAction中实现
 */
extern "C" {void PointerActionHandler(ActionHandler  handler){
    actionHandler = handler;
    NSLog(@"PutIntPtr UserFsHandler 指针内存地址 ===>> %p",&actionHandler);
   }
}

/**
 * unity call ios 主动接收 函数指针
 * UserFriendsHandler 用于ios回调 "当前用户好友列表"，在👇🏻GetUserFriends中实现
 */
extern "C" {void PointerUserFriendsHandler(UserFriendsHandler  handler){
    userFriendsHandler = handler;
    NSLog(@"PutIntPtr UserFsHandler 指针内存地址 ===>> %p",&userFriendsHandler);
   }
}

/**
 * unity call ios 主动接收 函数指针
 * InviteFriendHandler 用于ios回调 "接收好友邀请" ，在👇🏻GetInviteInfo中实现
 */
extern "C" {void PointerInviteFriendHandler(InviteFriendHandler  handler){
    inviteFriendHandler = handler;
    NSLog(@"PutIntPtr UserFsHandler 指针内存地址 ===>> %p",&inviteFriendHandler);
   }
}

/**
 * unity call ios 主动接收 函数指针
 * InviteFriendHandler 用于ios回调 "接收好友邀请" ，在👇🏻GetInviteInfo中实现
 */
extern "C" {void PointerGetRankHandler(GetRankHandler  handler){
    getRankHandler = handler;
    NSLog(@"PutIntPtr GetRankHandler 指针内存地址 ===>> %p",&getRankHandler);
   }
}

extern "C" {void PointerRotateHandler(RotateHandler  handler){
    rotateHandler = handler;
    NSLog(@"PutIntPtr RotateHandler 指针内存地址 ===>> %p",&rotateHandler);
   }
}


extern "C" {void PointerGameEndResponseHandler(GameEndResponseHandler  handler){
    gameEndResponseHandler = handler;
    NSLog(@"PutIntPtr GameEndResponseHandler 指针内存地址 ===>> %p",&gameEndResponseHandler);
   }
}


/**
* unity获取用户信息 -->> 解析从Spotr App的传过来的RL_Seme  ios返回json数据给游戏
*/
 char *  GetUserInfoJson(){
     
//     NSLog(@"Unity 请求用户信息 GetUserInfoJson ===>>");
     if ([instance existUserInfo]==NO){
         return MakeStringCopy("");
     }else{
         const char * cuschart = [[CacheTool getUserInfo] UTF8String];
//         NSLog(@"IOS_SKD 回调用户信息 GetUserInfoJson ===> %@",[CacheTool getUserInfo]);
         //要先copy 不然c#调用free的时候回闪退
         return MakeStringCopy(cuschart);
     }
     
}

/**
* unity获取用户好友列表 -->> ios端根据用户token值请求http好友列表 ios将列表json的数组数据传给unity
*/
void GetUserFriends(){
//    NSLog(@"Unity 请求好友列表 GetUserFriends ===>>");
    if ([instance existUserInfo]==NO){
        return;
    }
    [HTTPDataProcession getFriendsList:^(int code, const char *jsonString, NSMutableArray *dataArr){
        NSLog(@"IOS_SKD 回调好友列表 GetUserFriends ===> %s",jsonString);
        userFriendsHandler(code,jsonString);//异步回调
    }];
}

/**
* Unity call ios 获取游戏榜单数据
 *if (type == 0) "world" else "friend"
 *ios 请求完数据后用 PointerGetRankHandler 回调数据给unity
*/
void GetRank(int type){
//    NSLog(@"Unity 获取榜单列表数据 GetRank ===>> %d",type);
    if ([instance existUserInfo]==NO){
        return;
    }
    [HTTPDataProcession GetRank:type rankDataBlock:^(const char *jsonString){
        NSLog(@"IOS_SKD 回调 榜单列表数据 GetRank ===>> %d %s",type,jsonString);
        getRankHandler(type,jsonString);
    }];

}

/**
* 游戏在准备界面  Unity call ios申请申请邀请信息，ios用inviteFriendHandler指针回调数据给unity
*/
void GetInviteInfo(){
    
    NSLog(@"Unity获取好友邀请信息 GetInviteInfo ===>>");
    if ([instance existUserInfo]==NO){
        return;
    }
    //user字典 -> 字符串 -> Char
    const char * userChar = [[CacheTool getInviteUser] UTF8String];
    //info字符串 -> Char
    const char * infoChar =[[CacheTool getInviteInfo] UTF8String];
    NSLog(@"IOS_SKD 回调好友邀请信息 GetInviteInfo ===>>  %s , %s",userChar,infoChar);
    if (infoChar!=nil&&strlen(infoChar)>1) {
            inviteFriendHandler(0,userChar,infoChar);
    }
    //
}

/**
* Unity call ios 主动邀请好友（跳舞和跑酷游戏）
* friendid: 游戏好友ID
* info: 邀请信息
*/
void InviteFriend(int friendid,char * info){
    
    NSLog(@"Unity 点击邀请好友 InviteFriend ===>> %s",info);
    
    if ([instance existUserInfo]==NO){
        return;
    }
    NSString * inviteInof = [NSString stringWithFormat:@"%s",info];
    [HTTPDataProcession inviteFriends:friendid inviteInfo:inviteInof  inviteDataBlock:^(NSString *jsonString){
//        NSLog(@"IOS_SKD 回调点击邀请好友事件 InviteFriend ===>>");
        dispatch_async(dispatch_get_main_queue(), ^{
        [PopupView showCusHUDA:jsonString];
        });
    }];
    
}

/**
* Unity call ios 弹出邀请好友弹窗（三轮车游戏）
* code: 邀请信息
* info: 邀请信息
*/
void ShowInviteFriend(int code, char * info){
    NSLog(@"Unity 请求打开好友列表弹窗 ShowInviteFriend ===>> %s",info);
    if ([instance existUserInfo]==NO){
        return;
    }
    NSString * inviteInof = [NSString stringWithFormat:@"%s",info];
    [BTDataInstance showInviteFriend:code inviteInof:inviteInof];
}


/**
 * 游戏开始
 */
void GameStart(){
   NSLog(@"Unity 请求开始游戏 GameStart ===>>");
   if ([instance existUserInfo]==NO){
        return;
   }
    //蓝牙
    [BTDataInstance gameStartInitData];
    //http
    [HTTPDataProcession gameStart];
}


/**
* 游戏结束
* level: level
* score: score
* record: record
* mode: mode
* opponentId: opponentId
*/
void GameEnd(int level, double score, int record, int mode, int opponentId){
    
    NSLog(@"Unity 请求结束游戏 GameEnd ===>> %d %f %d %d %d",level,score,record,mode,opponentId);
    if ([instance existUserInfo]==NO){
        return;
    }
    [BTDataInstance gameEndInitData];
    //http
    [HTTPDataProcession gameEnd];
    //上传数据
    [HTTPDataProcession postGameRecord:level score:score record:record mode:mode opponentId:opponentId gameEndDataBlock:^(const char * jsonString){
        NSLog(@"IOS_SKD 回调结束游戏请求 GameEnd ===> %s",jsonString);
        gameEndResponseHandler(0,jsonString);
    }];
    
}



/**
* 搜索设备
* type: 设备ID
*/
void SearchDevice(int type){
    //unity 有两个search按钮 type 0是主设备 1是副设备
    NSLog(@"Unity 请求搜索设备 type ===>> %d",type);
    if ([instance existUserInfo]==NO){
        return;
    }
    [BTDataInstance searchBLEAction:type];
    
}


/**
* 链接设备
* type: 设备ID
*/
void ConnectDevice(int type){
    NSLog(@"Unity 请求链接设备 ConnectDevice ===>> %d",type);
    if ([instance existUserInfo]==NO){
        return;
    }
    //unity 有两个connect按钮 type 0是第一个玩家 1是第二个玩家
}

/**
* unity可以主动断开链接
* type: 设备类型 0: 主， 1: 副
*/
void DisConnectDevice(int type){
    NSLog(@"Unity 请求断开蓝牙链接 disConnectDevice ===>> %d",type);
    if ([instance existUserInfo]==NO){
        return;
    }
    [BTDataInstance disConnedctBle:type];
}


/**
* 震动
* type: 设备ID
* duration: 时长 ms [100 .. 1000]
*/
void  Vibrate(int type,int duration){
    if ([instance existUserInfo]==NO){
        return;
    }
    [BTDataInstance vibrationAction:type duration:duration leftOrRight:0];

}

/**
* 震动
* type: 设备ID
* duration: 时长 ms [100 .. 1000]
*/
void  VibrateS(int type,int duration,int leftOrRight){
    if ([instance existUserInfo]==NO){
        return;
    }
    NSLog(@"Unity 请求震动 VibrateS ===>> %d",leftOrRight);
    [BTDataInstance vibrationAction:type duration:duration leftOrRight:leftOrRight];
}

/**
 * Unity call ios 获取鞋子角度
*/
int NativeGetAttX(int cusId){
    if (cusId==0) {
        return BTDataInstance.main_nativeAttX;
    }else{
        return BTDataInstance.vice_nativeAttX;
    }
}


/**
* 投屏
*/
void ScreenProjection(){
    NSLog(@"Unity 请求投屏事件 ScreenProjection ===>>");
    if ([instance existUserInfo]==NO){
        return;
    }
}

/**
* Unity call ios 返回趣动app
*/
void OnBackPressed(){
    
    NSLog(@"Unity 返回app OnBackPressed");
    NSString * urlStr = @"com.cheedo.oujia://";
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:urlStr]]){
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlStr] options:@{} completionHandler:nil];
    }
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        //杀死进程
        kill(getpid(), 9);
    });
    
}
