//
//  MKRWIFIDeviceManager.m
//  MKRAVPlayer
//
//  Created by yyqxiaoyin on 2019/4/16.
//

#import "MKRWIFIDeviceManager.h"
#import "NSString+MKRRadioManagerAdd.h"
#import "UIDevice+MKRRadioManagerAdd.h"
#import <pthread.h>
#import <libAS-Control/ASControlTools.h>

static inline void wd_main_queue(void (^block)(void)){
    if (pthread_main_np()) {
        block();
    }else{
        dispatch_async(dispatch_get_main_queue(), block);
    }
}

@interface MKRWIFIDeviceManager () <ASControlDelegate> {
    int _upnpErrorCode;
    NSMutableArray *_baseUrlArray;
    dispatch_source_t _searchTimer;
}

@property (nonatomic, strong) NSMutableArray *currentDevices;

@property (nonatomic, strong) NSHashTable *listeners;

@end

@implementation MKRWIFIDeviceManager

- (instancetype)init {
    if (self = [super init]) {
        _upnpErrorCode = -1;
        [ASControlTools sharedInstanceUPNP].delegate = self;
    }
    return self;
}

+ (instancetype)shareManager {
    static MKRWIFIDeviceManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[MKRWIFIDeviceManager alloc] init];
    });
    return manager;
}

- (void)addDeviceManagerListener:(id<MKRWIFIDeviceManagerDelegate>)listener{
    if (![self.listeners containsObject:listener]){
        [self.listeners addObject:listener];
    }
}

- (void)removeDeviceManagerListener:(id<MKRWIFIDeviceManagerDelegate>)listener{
    if ([self.listeners containsObject:listener]) {
        [self.listeners removeObject:listener];
    }
}

- (NSInteger)startUpnp {
    NSString *userPhoneName = [[UIDevice currentDevice] name];
    NSString *sharePath = NSHomeDirectory();
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *DocumentSharePath = [paths objectAtIndex:0];
    NSString *sharePath2 = NSTemporaryDirectory();
    NSArray *dirArgv =[[NSArray alloc] initWithObjects:DocumentSharePath,sharePath2,nil];
    libupnp_RELoadUpnp();
    _upnpErrorCode = libupnp_UpnpStartTest([UIDevice currentDeviceMacAddress],userPhoneName,2,dirArgv,[UIDevice currentDeviceInfo],7);
    if (_upnpErrorCode == 0) {
        NSLog(@"upnp初始化成功");
        _upnpErrorCode = libupnp_UpnpSetWebServerRootDir(sharePath);
    }else if(_upnpErrorCode == -100) {
        NSLog(@"UpnpStart 无网络连接!! ==> %d ", _upnpErrorCode);
    }else{//UPNP_ERROR
        NSLog(@"UpnpStart Error!! ==>  %d" ,_upnpErrorCode);
    }
    return _upnpErrorCode;
}

- (void)searchDeviceWithSearchTime:(int)searchTime
                         timeBlock:(void(^)(NSInteger time,NSArray <NSDictionary *>*devices))timeBlock {
    if (_upnpErrorCode == 0) {//开始搜索设备
        [self checkBaseURL];
        libupnp_BuildFilesList();
        libupnp_SearchDevice(20);
    } else {
        [self startUpnp];
    }
    __block int count = searchTime +1;
    _searchTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    dispatch_source_set_timer(_searchTimer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(_searchTimer, ^{
        if (timeBlock) {
            wd_main_queue(^{
                timeBlock(count,self.currentDevices);
            });
        }
        count --;
        if (count == 0) {
            dispatch_source_cancel(self->_searchTimer);
        }
    });
    dispatch_source_set_cancel_handler(_searchTimer, ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"搜索结束");
        });
    });
    dispatch_resume(_searchTimer);
}

- (void)checkBaseURL{
    NSMutableArray *baseURLArray = [NSMutableArray array];
    for (NSString *baseValue in _baseUrlArray) {
        NSString *tempStr = [baseValue stringByReplacingOccurrencesOfString:@"49152" withString:@"MaoKing"];
        tempStr = [tempStr stringByReplacingOccurrencesOfString:@"49153" withString:@"MaoKing"];
        tempStr = [tempStr stringByReplacingOccurrencesOfString:@"49154" withString:@"MaoKing"];
        [baseURLArray addObject:[tempStr stringByReplacingOccurrencesOfString:@"MaoKing" withString:@"49152"]];
        [baseURLArray addObject:[tempStr stringByReplacingOccurrencesOfString:@"MaoKing" withString:@"49153"]];
        [baseURLArray addObject:[tempStr stringByReplacingOccurrencesOfString:@"MaoKing" withString:@"49154"]];
    }
    if([baseURLArray count] > 0)libupnp_FirstCheckByBaseURL((int)[baseURLArray count] , baseURLArray);
}

#pragma mark - ASControlDelegate

-(void)ReceivedPlayCallBack:(NSString *)nUDN{
    NSLog(@"%s",__func__);
}

-(void)ReceivedPauseCallBack:(NSString *)nUDN{
    NSLog(@"%s",__func__);
}

-(void)ReceivedStopCallBack:(NSString *)nUDN{
    NSLog(@"%s",__func__);
}

-(void)ReceivedSetVolumeCallBack:(NSString *)nUDN Volume:(NSInteger)Volume{
    NSLog(@"%s",__func__);
}

-(void)ReceivedSetMuteCallBack:(NSString *)nUDN Mute:(NSInteger)Mute{
    NSLog(@"%s",__func__);
}

-(void)ReceivedSetZoneMuteCallBack:(NSString *)nUDN Mute:(NSInteger)Mute{
    NSLog(@"%s",__func__);
}

-(void)ReceivedSetGroupIdCallBack:(NSString *)nUDN GrouId:(NSString *)GroupId{
    NSLog(@"%s",__func__);
}

-(void)ReceivedSetSleepStateCallBack:(NSString *)nUDN SleepState:(NSString *)SleepState{
    NSLog(@"%s",__func__);
}

-(void)ReceivedSetSoundSourceCallBack:(NSString *)nUDN SoundSource:(NSString *)SoundSource{
    NSLog(@"%s",__func__);
}

-(void)ReceivedSetVolumeChannelCallBack:(NSString *)nUDN Channel:(NSString *)Channel {
    NSLog(@"ReceivedSetVolumeChannelCallBack-------------%@ ",Channel);
}

-(void)ReceivedSetZoneVolumeCallBack:(NSString *)nUDN Volume:(NSInteger)Volume {
    NSLog(@"%s",__func__);
}

-(void)CallBackRemoveZoneMedia:(NSString *)nByeUDN BaseURL:(NSString *)BaseURL{
    NSLog(@"%s",__func__);
    
}

-(void)CallBackRemoveRenderer:(NSString *)nByeUDN BaseURL:(NSString *)BaseURL
{
    NSLog(@"CallBackRemoveRenderer---------%@",nByeUDN);
    NSLog(@"%s",__func__);
}

-(void)CallBackRemoveDMS:(NSString *)nByeUDN BaseURL:(NSString *)BaseURL{
    NSLog(@"%s",__func__);
}

-(void)CallBackAddZoneMedia:(NSArray *)nStr Size:(NSInteger)size{
    NSLog(@"搜索到设备：%@",nStr);
    NSLog(@"%s",__func__);
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
      [self addDevice:nStr];
    });
    
}

- (void)updateClockID:(NSString *)clockID clockDic:(NSDictionary *)clockDic clockTime:(NSString *)clockTime operationType:(BOOL)isOn deleteClock:(BOOL)isDelete{
    NSLog(@"%s",__func__);
}

-(void)CallBackAddMediaServer:(NSArray *)nStr Size:(NSInteger)size{
    NSLog(@"%s",__func__);
}


-(void)CallBackAddMediaRenderer:(NSArray *)nStr Size:(NSInteger)size{
    NSLog(@"%s",__func__);
}


-(void)ReceivedChangeChannelCallBack:(NSString *)nUDN Channel:(NSString *)channel{
    NSLog(@"%s",__func__);
}

-(void)getLocalIp:(NSString *)Ip{
    NSLog(@"%s",__func__);
}

-(void)AddLocalResource:(NSArray *)oneSongID3Info{
    NSLog(@"%s",__func__);
}

-(void)UpdateLocalResourceFinish{
    NSLog(@"%s",__func__);
}

- (void)addDevice:(NSArray *)array {
    
    NSMutableDictionary *deviceDict = [NSMutableDictionary dictionary];
    [deviceDict setObject:array[0] forKey:@"deviceName"];
    [deviceDict setObject:array[1] forKey:@"deviceUUID"];
    [deviceDict setObject:array[2] forKey:@"deviceBaseUrl"];
    [deviceDict setObject:array[5] forKey:@"connectionManagerUrl"];
    [deviceDict setObject:array[7] forKey:@"avTransportUrl"];
    [deviceDict setObject:array[9] forKey:@"renderingControlUrl"];
    [deviceDict setObject:array[11] forKey:@"groupManagementUrl"];
    NSArray *deviceInfo = [[ASControlTools sharedInstanceUPNP] libupnp_GetDeviceInfo:array[11] ServiceTYPE:array[10]];
    if(deviceInfo == nil || [deviceInfo isEqual:[NSNull null]]){
        return;
    }
    [deviceDict setObject:deviceInfo[0] forKey:@"devGId"];
    [deviceDict setObject:deviceInfo[1] forKey:@"devWiFiDB"];
    [deviceDict setObject:[deviceInfo[16] length]?deviceInfo[16]: @"AWAKE" forKey:@"devSleepStatus"];
    [deviceDict setObject:[deviceInfo[17] length]?deviceInfo[17]: @"WIFI" forKey:@"devSource"];
    [deviceDict setObject:[deviceInfo[28] length]?deviceInfo[28]:@"WIFI" forKey:@"devSourceList"];
    [deviceDict setObject:deviceInfo[12] forKey:@"channelLR"];
    [deviceDict setObject:[deviceInfo[29] length] ? deviceInfo[29]: @"0.0.0.0" forKey:@"devType"];
    [deviceDict setObject:[deviceInfo[33] length]? deviceInfo[33]:@"NULL" forKey:@"devPower"];
    [deviceDict setObject:[deviceInfo[36] length] ? deviceInfo[36]:@"NULL" forKey:@"devUserID"];
    NSString *devFlag = [NSString stringWithFormat:@"%@-%@",deviceInfo[9],deviceInfo[10]];
    [deviceDict setObject:devFlag forKey:@"devFlag"];
    [deviceDict setObject:[deviceInfo[18] length] ?deviceInfo[18]:@"MJ_M" forKey:@"devProductModel"];
    [deviceDict setObject:[deviceInfo[32] length] ?deviceInfo[32]:@"null" forKey:@"devClockStr"];
    [deviceDict setObject:[deviceInfo[39] length] ?deviceInfo[39] :@"0" forKey:@"devOpenLowPowerNotice"];
    [deviceDict setObject:[deviceInfo[19] length] ? deviceInfo[19] : @"1.0.0" forKey:@"devVersion"];
    [deviceDict setObject:[deviceInfo[41] length] ? deviceInfo[41] :@"" forKey:@"devDuerAccessToken"];
    [deviceDict setObject:[deviceInfo[42] length] ?deviceInfo[42] : @"" forKey:@"devDuerRefreshToken"];
    [deviceDict setObject:deviceInfo[13] forKey:@"volume"];
    [deviceDict setObject:deviceInfo[14] forKey:@"mute"];
    [deviceDict setObject:[deviceInfo[40] length] ?deviceInfo[40] :@"-1" forKey:@"devPauseShutDownTime"];
    NSString *devNowStatus = [deviceInfo[2] length] ? deviceInfo[2] : @"STOPPED";
    [deviceDict setObject:devNowStatus forKey:@"devNowStatus"];
    [deviceDict setObject:@"REPEAT_ALL" forKey:@"devNowPlayMode"];
    NSURL *url = [NSURL URLWithString:array[2]];
    [deviceDict setObject:url.URLByDeletingLastPathComponent.absoluteString?:@"" forKey:@"devIP"];
    if([devNowStatus isEqualToString:@"PAUSED_PLAYBACK"]){
        NSString *devNowPlaying = [NSString stringWithFormat:@"Pause:%@",deviceInfo[3]];
        [deviceDict setObject:devNowPlaying forKey:@"devNowPlaying"];
    }else if([devNowStatus isEqualToString:@"PLAYING"]){
        [deviceDict setObject:deviceInfo[3] forKey:@"devNowPlaying"];
    }
    [deviceDict setObject:deviceInfo[4] forKey:@"devNowArtist"];
    if([deviceDict[@"devNowPlaying"] isEqualToString:@"Unknown:TrackMetaData Incomplete"]){
        [deviceDict setObject:@"No Music" forKey:@"devNowPlaying"];
    }
    if([deviceDict[@"devNowArtist"] isEqualToString:@"Unknown:TrackMetaData Incomplete"])
    {
        [deviceDict setObject:@"Unknown" forKey:@"devNowArtist"];
    }
    if(deviceDict[@"devNowArtist"] == nil||[deviceDict[@"devNowArtist"] isEqual:[NSNull null]]){
        [deviceDict setObject:@"Unknown" forKey:@"devNowArtist"];
    }
    [deviceDict setObject:@"1" forKey:@"isOnLine"];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"deviceUUID = %@",array[1]];
    BOOL isExist = [self.currentDevices filteredArrayUsingPredicate:predicate].count;
    if (!isExist) {
        [self.currentDevices addObject:deviceDict];
    }
    id<MKRWIFIDeviceManagerDelegate> obj;
    NSEnumerator *enumerator = [self.listeners objectEnumerator];
    while ((obj = [enumerator nextObject]) != nil) {
        wd_main_queue(^{
            [obj didSearchNewDevice:self.currentDevices];
        });
    }
}

- (void)setM3UList:(MKRM3UListModel *)m3uListModel {
    libupnp_SetNewM3UList(
                          m3uListModel.secondsList,
                          m3uListModel.artistList,
                          m3uListModel.titleList,
                          m3uListModel.urlList,
                          m3uListModel.cueList,
                          m3uListModel.startTimeList,
                          m3uListModel.endTimeList,
                          m3uListModel.vipCanPlay,
                          m3uListModel.albumList,
                          m3uListModel.albumArtUriList,
                          m3uListModel.durationList,
                          m3uListModel.protocolInfoList,
                          m3uListModel.upnpclassList,
                          m3uListModel.channelNumList,
                          m3uListModel.songOrderList,
                          m3uListModel.userID,
                          m3uListModel.songIDList,
                          m3uListModel.songFromList,
                          m3uListModel.songAlbumIDList,
                          m3uListModel.channelNO,
                          m3uListModel.playModeString,
                          m3uListModel.timeString,
                          m3uListModel.channelPure,
                          m3uListModel.channelAlbumID,
                          m3uListModel.channelInfoString,
                          m3uListModel.userID,
                          m3uListModel.startIndex,
                          m3uListModel.endIndex,
                          m3uListModel.m3uSize,
                          @""
                          );
}

- (void)setAVTransportURIWithSong:(id <MKRRadioResorce>)song
                           device:(id <MKRUPnPDevice>)device
                           userID:(NSString *)userID {
    NSString *timestamp = [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970]];
    NSString *channelNumString = [NSString stringWithFormat:@"CHANNEL_UPDATE_%zd",song.songChannel];
    libupnp_SetAVTransportURI(
                              device.avTransportUrl,
                              song.songUrl,
                              song.songName,
                              song.songArtist,
                              song.songAlbum,
                              song.songAlbumCover,
                              @"0",
                              @"null",
                              @"null",
                              timestamp,
                              channelNumString,
                              @"0",
                              userID,
                              song.songInfoID,
                              @(song.songFrom).stringValue,
                              song.songAlbumID?:@""
                              );
}

- (void)playWithDevice:(id <MKRUPnPDevice>)device {
    libupnp_Play(device.avTransportUrl);
}

- (void)playSongWithChannelNO:(NSInteger)channelNO
                        index:(NSInteger)index
                       device:(id <MKRUPnPDevice>)device
                       userID:(NSString *)userID {
    NSString *playFlag = [NSString stringWithFormat:@"%zd-%zd",channelNO,index];
    NSString *playListUrl = [NSString stringWithFormat:@"%@/web/playlist",[ASControlTools sharedInstanceUPNP].myIp];
    NSString *timestamp = [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970]];
    libupnp_PlayNumFlag(
                        device.avTransportUrl,
                        playFlag,
                        timestamp,
                        userID,
                        playListUrl,
                        @"1"
                        );
}

- (void)playSongWithChannelNO:(NSInteger)channelNO
                       device:(id <MKRUPnPDevice>)device
                       userID:(NSString *)userID {
    [self playSongWithChannelNO:channelNO index:0 device:device userID:userID];
}

- (void)pauseWithDevice:(id <MKRUPnPDevice>)device {
    libupnp_Pause(device.avTransportUrl);
}

- (void)nextWithDevice:(id <MKRUPnPDevice>)device{
    libupnp_Previous(device.avTransportUrl);
}

- (void)previousWithDevice:(id <MKRUPnPDevice>)device{
    libupnp_Previous(device.avTransportUrl);
}

- (void)stopWithDevice:(id <MKRUPnPDevice>)device{
    libupnp_Stop(device.avTransportUrl);
}

- (void)setVolume:(int)volume device:(id <MKRUPnPDevice>)device{
    libupnp_SetZoneVolume(
                          device.groupManagementUrl,
                          @"urn:schemas-upnp-org:service:GroupManagement:1",
                          @"Master",
                          volume
                          );
}

- (void)seekToTimeInterval:(NSInteger)timeInterval device:(id <MKRUPnPDevice>)device {
    NSString *timeString = [NSString HHmmssFormatStrig:timeInterval];
    libupnp_SetMediaSeek(device.avTransportUrl, timeString);
}

- (void)clearChannelWithChannelNO:(NSString *)channelNO device:(id <MKRUPnPDevice>)device {
    NSString *channelID = [NSString stringWithFormat:@"CHANNEL_UPDATE_%@",channelNO];
    NSString *timestamp = [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970]];
    libupnp_SetChannelClear(device.groupManagementUrl, channelID, timestamp);
}

- (id <MKRRadioResorce>)getPlayingStatusWithDevice:(id <MKRUPnPDevice>)device {
    NSArray *dmrPositionInfo = [[ASControlTools sharedInstanceUPNP] libupnp_GetPositionInfo:device.avTransportUrl];
    if (dmrPositionInfo.count < 16) {
        //执行检查设备是否掉线操作
    }
    MKRRadioResorce *resource = [[MKRRadioResorce alloc] init];
    resource.songName = dmrPositionInfo[2];
    resource.songArtist = dmrPositionInfo[3];
    resource.songAlbumCover = dmrPositionInfo[5];
    resource.songUrl = dmrPositionInfo[7];
    resource.songInfoID = dmrPositionInfo[16];
    NSString *songFrom = dmrPositionInfo[17];
    if ([songFrom containsString:@"//"]) {
        NSArray *arr = [songFrom componentsSeparatedByString:@"//"];
        if (arr.count > 1) {
            songFrom = arr[1];
        }
    }
    resource.songFrom = (MKRResourcePlatform)[songFrom integerValue];
    NSString *channelString = dmrPositionInfo[8];
    if (![channelString containsString:@"Unknown:TrackMetaData Incomplete"]) {
        if ([channelString containsString:@"CHANNEL_UPDATE_"]) {
            resource.songChannel = [[channelString componentsSeparatedByString:@"CHANNEL_UPDATE_"].lastObject integerValue];
        } else {
            resource.songChannel = [channelString integerValue];
        }
    }
    //    resource.songLength = [self secondsFromTimeString:dmrPositionInfo[1]];
    //    MKRPlayResourceStatus *status = [MKRPlayResourceStatus new];
    //    status.currentTime = [[self secondsFromTimeString:dmrPositionInfo[10]] integerValue];
    //    status.totalTime = [oneSong.songLength integerValue];
    NSString *songChannelUid = [NSString stringWithFormat:@"%@-%@-%zd",self.userID,device.deviceUUID,resource.songChannel];
    resource.songChannelUid = songChannelUid;
    resource.songFlag = [NSString stringWithFormat:@"%@_%@_%@",songChannelUid,resource.songInfoID,songFrom];
    return resource;
}

- (NSMutableArray *)currentDevices {
    if (!_currentDevices) {
        _currentDevices = [NSMutableArray array];
    }
    return _currentDevices;
}

- (NSHashTable *)listeners{
    if (!_listeners) {
        _listeners = [NSHashTable weakObjectsHashTable];
    }
    return _listeners;
}

@end
