//
//  MyScriptTask.m
//  nochange
//
//  Created by mac on 2024/7/23.
//

#import "MyScriptTask.h"

#import "XSHelper.h"
#import "XSPhoneConfig.h"
#import "XSPhoneInfo.h"

#import "MyEventBus.h"
#import "XSHackIos.h"


#define total_ad_click 3

@interface MyScriptTask() 
{
    @private
    // 单次app任务
    NSString* _taskId;
    NSString* _appId;
    BOOL _lastAppTaskComplete;
    NSTimeInterval _lastAppTaskTime;
    NSTimeInterval _lastOcrTime;
    int _lastAppTaskCount;
    int _total;
    BOOL _stop;
    int _taskTimeout;
    int _workType;
    
    BOOL _lastTaskComplete; // 一个点击任务是否完成，按钮点击，广告展示，广告点击，广告回到页面
    NSTimeInterval _lastTaskTime;
    int _step; // 0 等待点击 1: 点击完成，2: 点击广告；3：广告点击完成，
    
    int _adTouchBefore;
   
  
    int _count;
    int _safeTop;
    
    NSMutableDictionary *_adShows;
    NSString *_idfa;
    CGFloat device_screen_width;
    CGFloat device_screen_height;
    
    int _loadCount;
}

@property (nonatomic, strong) NSMutableArray *inStack;
@property (nonatomic, strong) NSMutableArray *outStack;
@property (nonatomic, strong) dispatch_queue_t concurrentQueue;

@end

@implementation MyScriptTask

- (instancetype)init {
    self = [super init];
    if (self) {
        _currentId = 0;
        _concurrentQueue = dispatch_queue_create("com.xyzshell.adtask.queue", DISPATCH_QUEUE_CONCURRENT);
        _inStack = [NSMutableArray array];
        _outStack = [NSMutableArray array];
        _adShows = [[NSMutableDictionary alloc] init];
        
        _taskTimeout = 30;
        _workType = 1;
        
        _lastTaskComplete = YES;
        _stop = NO;
        _total = 0;
        _count = 0;
        _lastAppTaskComplete = YES;
        _lastAppTaskTime = [self getCurTime];
        _lastAppTaskCount = 0;
        _safeTop = 20;
        _adTouchBefore = 3;
        _taskId = @"0";
        _appId = @"";
        _loadCount = 0;
        _lastOcrTime = [self getCurTime];
        NSLog(@"OhNo Server Start %@", [[XSPhoneConfig sharedInstance] IPhoneName]);
        CGFloat screen_scale = [[UIScreen mainScreen] scale];
        self->device_screen_width = [UIScreen mainScreen].bounds.size.width * screen_scale;
        self->device_screen_height = [UIScreen mainScreen].bounds.size.height * screen_scale;
    }
    return self;
}

- (void) showStatus: (NSString *)data {
    [[MyEventBus sharedInstance] postEvent:@"UpdateStatus" withObject:data];
}

- (void) start {
    _stop = NO;
    
    [self runStartApp];
}

- (void) stop {
    _stop = YES;
}

- (int64_t)nextId {
    @synchronized (self) {
        self.currentId++;
        return self.currentId;
    }
}

- (int)enqueue:(id)item {
    int load = 0;
    dispatch_barrier_async(self.concurrentQueue, ^{
        NSDictionary *dic = item;
        NSLog(@"-ad log- add task:\n %@", dic);
        NSMutableDictionary *taskDic = [[NSMutableDictionary alloc] initWithDictionary:dic];
        [taskDic setValue:@([self nextId]) forKey:@"_id"];
        [self->_adShows setValue: dic[@"ad_time"] forKey:dic[@"adId"]];
        self ->_adTouchBefore = [dic[@"ad_touchBeforeMs"] intValue];
        [self.inStack addObject:taskDic];
        self->_count++;
        [self showStatus:[NSString stringWithFormat: @"队列任务数量:%d, loads:%@", self->_count, dic[@"ad_loads"]]];
    });
    return load;
}

- (id)dequeue {
    __block id result = nil;
    dispatch_barrier_sync(self.concurrentQueue, ^{
            if ([self.outStack count] == 0) {
                NSUInteger count = [self.inStack count];
                while (count > 0) {
                    [self.outStack addObject:[self.inStack lastObject]];
                    [self.inStack removeLastObject];
                    count--;
                }
            }
            
            if ([self.outStack count] > 0) {
                result = [self.outStack lastObject];
                [self.outStack removeLastObject];
            }
        });
        return result;
}

- (void) reset {
    _lastTaskComplete = YES;
    _lastTaskTime = [self getCurTime];
}



- (BOOL) isRun {
    return !_stop;;
}

- (void) run {
    dispatch_queue_t queue = dispatch_get_global_queue(0,0);
    dispatch_async(queue, ^{
        self.timer = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(proc) userInfo:nil repeats:YES];
        //timer 加入runloop
        [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];
        //开启runloop
        [[NSRunLoop currentRunLoop] run];
    });
}

- (void) completeTask {
    _lastTaskComplete = YES;
    _lastTaskTime = [self getCurTime];
    _lastAppTaskCount++;
}

- (void) adClosed: (ScriptTask *)task {
    [self showStatus:[NSString stringWithFormat:@"关闭：%@", task->adId]];
    [self completeTask];
}

- (void) loadIncrCount {
    self->_loadCount = self->_loadCount + 1;
}

-(void) restart {
    dispatch_barrier_sync(self.concurrentQueue, ^{
        _loadCount = 0;
        _lastTaskComplete = YES;
        _lastTaskTime = [self getCurTime];
        _lastAppTaskComplete = YES;
        _lastAppTaskTime = [self getCurTime];
        _lastAppTaskCount = 0;
        [self.outStack removeAllObjects];
        [self.inStack removeAllObjects];
        [_adShows removeAllObjects];
        _count = 0;
    });
}

- (void) killApp: (NSString *)pkgName {
    XSKillAppByName(pkgName);
}

- (void) runStartApp {
    [self restart];
    NSLog(@"-ad log- runStartApp");
    getChangeInfo(_idfa, ^(NSDictionary *dic) {
        if (!dic || [dic isEqual: [NSNull null]]) {
            NSLog(@"get change info dic is null");
            return;
        }
        NSDictionary *workInfo = dic[@"workerInfo"];
        if (!workInfo || [workInfo isEqual:[NSNull null]]) {
            NSLog(@"-ad log- not have task");
            return;
        }
        NSNumber *workType = workInfo[@"workType"];
        self->_workType = [workType intValue];
        if (self->_workType <= -1) {
            NSLog(@"-ad log- not have task");
            return;
        }
        self->_taskId = dic[@"id"];
        self->_idfa = dic[@"idfa"];
        
        saveChangeDataFile(dic);
        // NSNumber *taskTimeout = workInfo[@"taskTimeout"];
        
        self->_appId = dic[@"appId"];
        NSLog(@"-ad log- change %@", self->_appId);
        NSDictionary *safeAreaInsets = dic[@"safeAreaInsets"];
        if (safeAreaInsets) {
            NSString *top = safeAreaInsets[@"top"];
            if (top) {
                self->_safeTop = [top intValue];
            }
        }
        // 获取任务，开始启动
        //ScriptTask oldtask = {
        //    .appId = self->_appId
        //};
        [self killApp:self->_appId];
        // [self runStopScript:&oldtask];
        
        // 获取任务，开始启动
        //ScriptTask task = {
        //    .appId = self->_appId,
        //};
        dispatch_async(dispatch_get_main_queue(), ^{
            XSRemoteUnlock();
            usleep(5000);
            XSRemoteUnlock();
        });
        
        //[self runSystemRestartScript];
        
        // TODO: 备份数据
        NSString *appInfoPath = XSGetAppInfoPath(self->_appId);
        NSDictionary *appInfo = XSGetAppInfo(appInfoPath);
        
        XSClearAll(self->_appId);
        
        XSSaveAppInfo(appInfo, appInfoPath);
        
        
       
        
        [[UIApplication sharedApplication] performSelectorOnMainThread:@selector(beginIgnoringInteractionEvents) withObject:nil waitUntilDone:YES];
        [[UIApplication sharedApplication] performSelectorOnMainThread:@selector(endIgnoringInteractionEvents) withObject:nil waitUntilDone:YES];
        
        //[self runStartScript:&task];
        XSBringAppForeground(self->_appId);
    }, ^(NSError *err) {
        
    });
   
}
- (void) proc {
    @try {
        [self _proc];
    } @catch (NSException *exception) {
        NSLog(@"-ad- erro");
    }
}
- (void) _proc {
    if (_stop) {
        return;
    }
    NSLog(@"start proc task........");
    
    if (_workType < 1) {
        if (_count > 1 && ([self getCurTime] - _lastAppTaskTime) > 6) {
            [self runStartApp];
        } else if (([self getCurTime] - _lastAppTaskTime) > 20){
            [self runStartApp];
        }
       
        return;
    }
    if (_workType == 4) {
        if (_lastTaskComplete == YES) {
            _lastTaskComplete = NO;
            _lastTaskTime = [self getCurTime];
            ScriptTask sctask = {
                .idfa = _idfa,
                .appId = _appId,
                .ad = true,
                .adId = @""
            };
            AdTaskLogData logData = {
                .title = @"广告展示",
                .idfa = _idfa,
                .appid = _appId,
                .adid = @"",
                .message = @"",
                .level = 1,
                .ecpm = @(0)
            };
            self->_adTouchBefore = 10000;
            [[MyScriptTask sharedInstance] saveAdTaskLog:&logData];
            [[MyScriptTask sharedInstance] runAdTouchScript:&sctask];
            return;
        } else {
            if (([self getCurTime] - _lastTaskTime) > 18) {
                [self runStartApp];
                return;
            }
        }
    }
    
    
    if (self->_loadCount > 0) {
        if (_lastAppTaskCount >= self->_loadCount) {
            sleep(2);
            [self runStartApp];
            return;
        }
    }
   
    if (([self getCurTime] - _lastAppTaskTime) > 80) {
        [self runStartApp];
        return;
    }
    if (_lastTaskComplete == NO) {
        // 上次任务没有执行完，30秒不等待，继续下一个任务
        if (_lastTaskTime && ([self getCurTime] - _lastTaskTime) < _taskTimeout) {
            NSLog(@"last task running");
            return;
        }
    }

    @try {
        id task = [self dequeue];
        if (task) {
            _lastTaskComplete = NO;
            if (_lastAppTaskComplete == YES) {
                _lastAppTaskComplete = NO;
            }
            // 处理任务
            _lastTaskTime = [self getCurTime];
            NSMutableDictionary *taskData = task;
            NSLog(@"pad roc task: \n%@", taskData);
            NSString *type = taskData[@"type"];
            if ([type isEqual:@"click_btn"]) {
                NSLog(@"ad proc task: click_btn - begin");
                [self showStatus:[NSString stringWithFormat:@"点击：%@", taskData[@"adId"]]];
                NSNumber *x = taskData[@"x"];
                NSNumber *y = taskData[@"y"];
                FixedPoint point = {
                    .x = [x intValue],
                    .y = [y intValue]
                };
                ScriptTask st = { .btnLoc = &point, .appId=_appId };
                [self runAdShowScript:&st];
            }
        } else {
            if (_lastTaskTime &&  ([self getCurTime] - _lastTaskTime) > 20) {
                [self runStartApp];
                return;
            }
        }
    }
    @catch (NSException *exception) {
        NSLog(@"ad proc ex name: %@", exception.name);
        NSLog(@"ad proc ex reason: %@", exception.reason);
        [self completeTask];
    }
    @finally {
        NSLog(@"ad proc end");
    }
}

- (BOOL) replaceScript: (NSString *)tplName scriptName: (NSString *)scriptName callback: (ScriptReplaceCallback)callback {
    NSString *scriptTpl = [self readScript:tplName];
    if (scriptTpl == nil) {
        NSLog(@"ad read script is nil");
        return NO;
    }
    NSLog(@"ad tpl script: %@", tplName);
    NSMutableString *newScript = [NSMutableString stringWithString:scriptTpl];
    callback(newScript);
    // NSLog(@"ad new script: %@", newScript);
    return [self saveScript:[newScript copy] name:scriptName];
}

- (void) runAdShowScript: (ScriptTask *) taskData {
    // 1. 写入按钮点击脚本
    NSLog(@"ad runAdShowScript");
    
    NSString *curApp = XSFrontMostAppId();
    if(![self->_appId isEqual:curApp]) {
        XSBringAppForeground(self->_appId);
        sleep(2);
    }
    usleep(5000);
    int x = taskData->btnLoc->x * 2;
    int y = taskData->btnLoc->y;
    int ny = y * 2  + (self->_safeTop / 2) - 10;
    
    
    /*
    BOOL flag = [self replaceScript:SCRIPT_TOUCH_BTN_TPL scriptName:SCRIPT_TOUCH_BTN callback:^(NSMutableString *newScript) {
   
      
        [MyHelper replaceMulStr:newScript oldStr:@"local btn_x = __BTN_X__" newStr:[NSString stringWithFormat:@"local btn_x = %d", x]];
        [MyHelper replaceMulStr:newScript oldStr:@"local btn_y = __BTN_Y__" newStr:[NSString stringWithFormat:@"local btn_y = %d", ny]];
        [MyHelper replaceMulStr:newScript oldStr:@"__APPID__" newStr:taskData->appId];
        
    }];
   
  
    // 2. 运行脚本
    if (flag) {
        NSLog(@"save script ok: %@", SCRIPT_TOUCH_BTN);
        NSString *res = [self runScript:SCRIPT_TOUCH_BTN];
        if (res) {
            NSLog(@"ad run script success: %@", SCRIPT_TOUCH_BTN);
            [self showStatus:[NSString stringWithFormat:@"运行点击按钮成功,%@",res]];
        } else {
            [self showStatus:[NSString stringWithFormat:@"运行点击按钮失败,%@",res]];
        }

    } else {
        NSLog(@"save script error: %@", SCRIPT_TOUCH_BTN);
        [self showStatus:@"保存按钮点击脚本失败"];
    }
    //*/
}

- (void) runStopScript: (ScriptTask *) taskData {
 
    BOOL flag = [self replaceScript:SCRIPT_KILL_ALL_TPL scriptName:SCRIPT_KILL_ALL callback:^(NSMutableString *newScript) {
        [XSHelper replaceMulStr:newScript oldStr:@"__APPID__" newStr:taskData->appId];
    }];
    if (flag) {
        // 结束所有相关app
        NSString *res = [self runScript:SCRIPT_KILL_ALL];
        if (res) {
            NSLog(@"-ad -log %@",res);
        }
    }
  
}

- (int) runAdTouchScript: (ScriptTask *) taskData {
    if (!taskData->ad) {
        // 没有广告展示
        NSLog(@"-ad log- touch btn No ad");
        [self completeTask];
        [self showStatus: [NSString stringWithFormat:@"广告展示失败:%@", taskData->adId]];
        return 0;
    }
    _lastTaskTime = [self getCurTime];
    /*
    NSLog(@"-ad log- run ad touch script: %@", SCRIPT_TOUCH_AD);
    BOOL flag = [self replaceScript:SCRIPT_TOUCH_AD_TPL scriptName:SCRIPT_TOUCH_AD callback:^(NSMutableString *newScript) {
        [MyHelper replaceMulStr:newScript oldStr:@"__APPID__" newStr:taskData->appId];
        [MyHelper replaceMulStr:newScript oldStr:@"__BEFORE__" newStr:[NSString stringWithFormat:@"%d", self->_adTouchBefore]];
    }];
    if (flag) {
        NSString *res = [self runScript:SCRIPT_TOUCH_AD];
        if (res) {
            NSLog(@"sc res: %@", res);
        }
       
    }
     */
    [self runTouchAdJs:self->_adTouchBefore];
    int show_ms = 5000;
    if ([_adShows objectForKey:taskData->adId]) {
        NSNumber *shows = _adShows[taskData->adId];
        show_ms = [shows intValue];
    }
    [self showStatus: [NSString stringWithFormat:@"广告展,%@", taskData->adId]];
    // 点击广告
    return show_ms;
}

- (void) runStartScript: (ScriptTask *) taskData {
    // 启动app 开始任务
    // 清除队列里面所有任务， 重置状态
    [self showStatus:@"start new task"];
    _lastTaskTime = [self getCurTime];
  
    BOOL flag = [self replaceScript:SCRIPT_START_TPL scriptName:SCRIPT_START callback:^(NSMutableString *newScript) {
        [XSHelper replaceMulStr:newScript oldStr:@"__APPID__" newStr:taskData->appId];
    }];
    if (flag) {
        NSString *res = [self runScript:SCRIPT_START];
        if (res) {
            NSLog(@"-ad- start task：%@", res);
        }
    }
}

- (void) runSystemRestartScript {
    NSString *res = [self runScript:@"close_not_now.lua"];
    if (res) {
        NSLog(@"kill a all");
    }
}

- (NSString *) runScript: (NSString *)script {
    /*
    NSString *url = [NSString stringWithFormat:@"http://127.0.0.1:8080/control/start_playing?path=/%@", script];
    [XSHelper doGET:url withCallback:^(NSData* _data) {
        if (_data) {
            NSString *res = [MyHelper data2str:_data];
            [self showStatus:[NSString stringWithFormat: @"运行脚本成功，%@", res]];
        }
    } withError:^(NSError *err) {
        NSLog(@"run autouch script error");
    }];
   
    NSLog(@"run autouch script error");
     */
    return nil;
}

- (NSString *) stopScript: (NSString *)script {
    /*
    NSString *url = [NSString stringWithFormat:@"http://127.0.0.1:8080/control/stop_playing?path=/%@", script];
    [_http doGET:url callback:^(NSData* _data) {
        if (_data) {
            NSString *res = [MyHelper data2str:_data];
            [self showStatus:[NSString stringWithFormat: @"停止脚本成功，%@", res]];
        }
    }];
    NSLog(@"run autouch script error");
     */
    return nil;
}

- (NSString *) readScript: (NSString *)name {
    NSString *scriptPath = [self getScriptPath:name];
    return [XSHelper readFileText:scriptPath];
}

- (BOOL) saveScript: (NSString *)script name:(NSString *)name {
    NSString *scriptPath = [self getScriptPath:name];
    return [XSHelper saveFile:scriptPath text:script];
}

- (NSString *) getScriptPath: (NSString *) name {
    return [NSString stringWithFormat:@"/var/mobile/Library/AutoTouch/Scripts/%@", name];
}

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

- (void) logServer: (NSString *) info title: (NSString *)title {
    
}

- (void) saveAdTaskLog: (AdTaskLogData *)data {
    data->taskId = _taskId;
    data->iphoneId = [[XSPhoneConfig sharedInstance] IPhoneName];
    data->ipAddr = [[XSPhoneInfo sharedInstance] IPAddress];
    pushAdTaskLog(data);
}

- (NSString*) statusStr {
    NSString *runStatusStr = _stop ? @"已停止": @"运行中";
    return [NSString stringWithFormat:@"%@", runStatusStr];
}
- (NSString*) appid {
    return _appId;
}

- (void) runTouchAdJs: (NSInteger) befor {
    /*
    JsRunner *runner = [[JsRunner alloc] init];
    NSString *tmpCode = @"var beforeTouch = %@;"
    "var cur_app_id = \"%@\";"
    "var screen_w = %@;"
    "var screen_h = %@;";
    NSString *code = [NSString stringWithFormat:tmpCode, @(befor / 1000), [self appid], @(self->device_screen_width), @(self->device_screen_height)];
    NSLog(@"runTouchAdJs:%@", code);
    [runner runCode:code];
    [runner runJS:@"/var/mobile/Library/AutoTouch/Scripts/touch_ad.js" timeout:50 completion:^(JSValue *result, BOOL timedOut) {
        NSLog(@"runTouchAdJs end");
    }];
     */
}

+(instancetype)sharedInstance
{
    static MyScriptTask* _sharedInstance = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once (&oncePredicate, ^{
        _sharedInstance = [[MyScriptTask alloc] init];
    });
    return _sharedInstance;
}

@end
