//
//  IPTool.m
//  Open
//
//  Created by 雷俊博 on 2019/10/23.
//  Copyright © 2019 黄江涛 . All rights reserved.
//

#import "IPTool.h"

@implementation IPTool


+ (NSString *)getIdentifier
{
    //设备唯一标识符
    NSString *identifier = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
    
    return identifier;
}
//获取设备当前网络IP地址

+ (NSString *)getIPAddress:(BOOL)preferIPv4

{

NSArray *searchArray = preferIPv4 ?

@[ /*IOS_VPN @"/" IP_ADDR_IPv4, IOS_VPN @"/" IP_ADDR_IPv6,*/ IOS_WIFI @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6 ] :

@[ /*IOS_VPN @"/" IP_ADDR_IPv6, IOS_VPN @"/" IP_ADDR_IPv4,*/ IOS_WIFI @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4 ] ;

NSDictionary *addresses = [self getIPAddresses];

NSLog(@"addresses: %@", addresses);

__block NSString *address;

[searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)

{

address = addresses[key];

if(address) *stop = YES;

} ];

return address ? address : @"0.0.0.0";

}

//获取所有相关IP信息

+ (NSDictionary *)getIPAddresses

{

NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];

// retrieve the current interfaces - returns 0 on success

struct ifaddrs *interfaces;

if(!getifaddrs(&interfaces)) {

// Loop through linked list of interfaces

struct ifaddrs *interface;

for(interface=interfaces; interface; interface=interface->ifa_next) {

if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) {

continue; // deeply nested code harder to read

}

const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;

char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];

if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) {

NSString *name = [NSString stringWithUTF8String:interface->ifa_name];

NSString *type;

if(addr->sin_family == AF_INET) {

if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {

type = IP_ADDR_IPv4;

}

} else {

const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr;

if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) {

type = IP_ADDR_IPv6;

}

}

if(type) {

NSString *key = [NSString stringWithFormat:@"%@/%@", name, type];

addresses[key] = [NSString stringWithUTF8String:addrBuf];

}

}

}

// Free memory

freeifaddrs(interfaces);

}

return [addresses count] ? addresses : nil;

}



+ (NSString *)getIPAddress2 {
    NSString *address = @"error";
    struct ifaddrs *interfaces = NULL;
    struct ifaddrs *temp_addr = NULL;
    int success = 0;
    // retrieve the current interfaces - returns 0 on success
    success = getifaddrs(&interfaces);
    if (success == 0) {
        // Loop through linked list of interfaces
        temp_addr = interfaces;
        while(temp_addr != NULL) {
            if(temp_addr->ifa_addr->sa_family == AF_INET) {
                // Check if interface is en0 which is the wifi connection on the iPhone
                if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
                    // Get NSString from C String
                    address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
                }
            }
            temp_addr = temp_addr->ifa_next;
        }
    }
    // Free memory
    freeifaddrs(interfaces);
    return address;
}

//设备类型
+ (NSString *)DSMC_getDeviceType{
    //仅仅返回一个iPhone或者ipad没有具体型号
    //return [UIDevice currentDevice].model;
    
    // 需要#import "sys/utsname.h"
    struct utsname systemInfo;
    uname(&systemInfo);
    NSString *platform = [NSString stringWithCString:systemInfo.machine encoding:NSASCIIStringEncoding];
    
    //IPHONE
    if([platform isEqualToString:@"iPhone1,1"])  return@"iPhone 2G";
    if([platform isEqualToString:@"iPhone1,2"])  return@"iPhone 3G";
    if([platform isEqualToString:@"iPhone2,1"])  return@"iPhone 3GS";
    if([platform isEqualToString:@"iPhone3,1"])  return@"iPhone 4";
    if([platform isEqualToString:@"iPhone3,2"])  return@"iPhone 4";
    if([platform isEqualToString:@"iPhone3,3"])  return@"iPhone 4";
    if([platform isEqualToString:@"iPhone4,1"])  return@"iPhone 4S";
    if([platform isEqualToString:@"iPhone5,1"])  return@"iPhone 5";
    if([platform isEqualToString:@"iPhone5,2"])  return@"iPhone 5";
    if([platform isEqualToString:@"iPhone5,3"])  return@"iPhone 5c";
    if([platform isEqualToString:@"iPhone5,4"])  return@"iPhone 5c";
    if([platform isEqualToString:@"iPhone6,1"])  return@"iPhone 5s";
    if([platform isEqualToString:@"iPhone6,2"])  return@"iPhone 5s";
    if([platform isEqualToString:@"iPhone7,1"])  return@"iPhone 6 Plus";
    if([platform isEqualToString:@"iPhone7,2"])  return@"iPhone 6";
    if([platform isEqualToString:@"iPhone8,1"])  return@"iPhone 6s";
    if([platform isEqualToString:@"iPhone8,2"])  return@"iPhone 6s Plus";
    if([platform isEqualToString:@"iPhone8,4"])  return@"iPhone SE";
    if([platform isEqualToString:@"iPhone9,1"])  return@"iPhone 7";
    if([platform isEqualToString:@"iPhone9,2"])  return@"iPhone 7 Plus";
    if([platform isEqualToString:@"iPhone10,1"]) return@"iPhone 8";
    if([platform isEqualToString:@"iPhone10,4"]) return@"iPhone 8";
    if([platform isEqualToString:@"iPhone10,2"]) return@"iPhone 8 Plus";
    if([platform isEqualToString:@"iPhone10,5"]) return@"iPhone 8 Plus";
    if([platform isEqualToString:@"iPhone10,3"]) return@"iPhone X";
    if([platform isEqualToString:@"iPhone10,6"]) return@"iPhone X";
    if([platform isEqualToString:@"iPhone11,2"]) return@"iPhone XS";
    if([platform isEqualToString:@"iPhone11,4"]) return@"iPhone XS Max";
    if([platform isEqualToString:@"iPhone11,6"]) return@"iPhone XS Max";
    if([platform isEqualToString:@"iPhone11,8"]) return@"iPhone XR";
    
    //IPOD
    if([platform isEqualToString:@"iPod1,1"])  return@"iPod Touch 1G";
    if([platform isEqualToString:@"iPod2,1"])  return@"iPod Touch 2G";
    if([platform isEqualToString:@"iPod3,1"])  return@"iPod Touch 3G";
    if([platform isEqualToString:@"iPod4,1"])  return@"iPod Touch 4G";
    if([platform isEqualToString:@"iPod5,1"])  return@"iPod Touch 5G";
    if([platform isEqualToString:@"iPod7,1"])  return@"iPod Touch 6G";
    
    //IPAD
    if([platform isEqualToString:@"iPad1,1"])  return@"iPad 1G";
    if([platform isEqualToString:@"iPad2,1"])  return@"iPad 2";
    if([platform isEqualToString:@"iPad2,2"])  return@"iPad 2";
    if([platform isEqualToString:@"iPad2,3"])  return@"iPad 2";
    if([platform isEqualToString:@"iPad2,4"])  return@"iPad 2";
    if([platform isEqualToString:@"iPad2,5"])  return@"iPad Mini 1G";
    if([platform isEqualToString:@"iPad2,6"])  return@"iPad Mini 1G";
    if([platform isEqualToString:@"iPad2,7"])  return@"iPad Mini 1G";
    if([platform isEqualToString:@"iPad3,1"])  return@"iPad 3";
    if([platform isEqualToString:@"iPad3,2"])  return@"iPad 3";
    if([platform isEqualToString:@"iPad3,3"])  return@"iPad 3";
    if([platform isEqualToString:@"iPad3,4"])  return@"iPad 4";
    if([platform isEqualToString:@"iPad3,5"])  return@"iPad 4";
    if([platform isEqualToString:@"iPad3,6"])  return@"iPad 4";
    if([platform isEqualToString:@"iPad4,1"])  return@"iPad Air";
    if([platform isEqualToString:@"iPad4,2"])  return@"iPad Air";
    if([platform isEqualToString:@"iPad4,3"])  return@"iPad Air";
    if([platform isEqualToString:@"iPad4,4"])  return@"iPad Mini 2G";
    if([platform isEqualToString:@"iPad4,5"])  return@"iPad Mini 2G";
    if([platform isEqualToString:@"iPad4,6"])  return@"iPad Mini 2G";
    if([platform isEqualToString:@"iPad4,7"])  return@"iPad Mini 3";
    if([platform isEqualToString:@"iPad4,8"])  return@"iPad Mini 3";
    if([platform isEqualToString:@"iPad4,9"])  return@"iPad Mini 3";
    if([platform isEqualToString:@"iPad5,1"])  return@"iPad Mini 4";
    if([platform isEqualToString:@"iPad5,2"])  return@"iPad Mini 4";
    if([platform isEqualToString:@"iPad5,3"])  return@"iPad Air 2";
    if([platform isEqualToString:@"iPad5,4"])  return@"iPad Air 2";
    if([platform isEqualToString:@"iPad6,3"])  return@"iPad Pro 9.7";
    if([platform isEqualToString:@"iPad6,4"])  return@"iPad Pro 9.7";
    if([platform isEqualToString:@"iPad6,7"])  return@"iPad Pro 12.9";
    if([platform isEqualToString:@"iPad6,8"])  return@"iPad Pro 12.9";
    if([platform isEqualToString:@"iPad6,11"])  return@"iPad 5";
    if([platform isEqualToString:@"iPad6,12"])  return@"iPad 5";
    if([platform isEqualToString:@"iPad7,1"])  return@"iPad Pro 2G 12.9";
    if([platform isEqualToString:@"iPad7,2"])  return@"iPad Pro 2G 12.9";
    if([platform isEqualToString:@"iPad7,3"])  return@"iPad Pro 10.5";
    if([platform isEqualToString:@"iPad7,4"])  return@"iPad Pro 10.5";
    if([platform isEqualToString:@"iPad7,5"])  return@"iPad 6";
    if([platform isEqualToString:@"iPad7,6"])  return@"iPad 6";
    
    //模拟器
    if([platform isEqualToString:@"i386"])    return@"iPhone Simulator";
    if([platform isEqualToString:@"x86_64"])  return@"iPhone Simulator";
    
    return platform;
}


+ (NSString *)getCurrentDeviceModel{
   struct utsname systemInfo;
   uname(&systemInfo);
   
   NSString *deviceModel = [NSString stringWithCString:systemInfo.machine encoding:NSASCIIStringEncoding];

    return deviceModel;
}

+ (NSString *)getCurrentDeviceType {
    NSString* model = [self getCurrentDeviceModel];
    if ([model containsString:@"iPhone"]) {
        return @"1";
    }else if ([model containsString:@"iPad"]){
        return @"2";
    }else{
        return @"0";
    }
}

+ (NSString *)getIDFA
{
     NSString *idfa = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
    
    return idfa;
}
+ (NSString *)getIDFV
{
    NSString * IDFV = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
    
    return IDFV;
}
+ (NSString *)getSystemVersion
{
     NSString * str = [NSString stringWithFormat:@"IOS%.2f",[[[UIDevice currentDevice] systemVersion]   floatValue]];

      return str;

   
}


#pragma mark - 获取MAC地址
/*
 * 获取设备物理地址
 */
+ (nullable NSString *)getMacAddress {
    res_9_init();
    int len;
    //get currnet ip address
    NSString *ip = [self currentIPAddressOf:IOS_WIFI];
    if(ip == nil) {
        fprintf(stderr, "could not get current IP address of en0\n");
        return DUMMY_MAC_ADDR;
    }//end if
    
    //set port and destination
    _res.nsaddr_list[0].sin_family = AF_INET;
    _res.nsaddr_list[0].sin_port = htons(MDNS_PORT);
    _res.nsaddr_list[0].sin_addr.s_addr = [self IPv4Pton:ip];
    _res.nscount = 1;
    
    unsigned char response[NS_PACKETSZ];
    
    
    //send mdns query
    if((len = res_9_query(QUERY_NAME, ns_c_in, ns_t_ptr, response, sizeof(response))) < 0) {
        
        fprintf(stderr, "res_search(): %s\n", hstrerror(h_errno));
        return DUMMY_MAC_ADDR;
    }//end if
    
    //parse mdns message
    ns_msg handle;
    if(ns_initparse(response, len, &handle) < 0) {
        fprintf(stderr, "ns_initparse(): %s\n", hstrerror(h_errno));
        return DUMMY_MAC_ADDR;
    }//end if
    
    //get answer length
    len = ns_msg_count(handle, ns_s_an);
    if(len < 0) {
        fprintf(stderr, "ns_msg_count return zero\n");
        return DUMMY_MAC_ADDR;
    }//end if
    
    //try to get mac address from data
    NSString *macAddress = nil;
    for(int i = 0 ; i < len ; i++) {
        ns_rr rr;
        ns_parserr(&handle, ns_s_an, 0, &rr);
        
        if(ns_rr_class(rr) == ns_c_in &&
           ns_rr_type(rr) == ns_t_ptr &&
           !strcmp(ns_rr_name(rr), QUERY_NAME)) {
            char *ptr = (char *)(ns_rr_rdata(rr) + 1);
            int l = (int)strcspn(ptr, "@");
            
            char *tmp = calloc(l + 1, sizeof(char));
            if(!tmp) {
                perror("calloc()");
                continue;
            }//end if
            memcpy(tmp, ptr, l);
            macAddress = [NSString stringWithUTF8String:tmp];
            free(tmp);
        }//end if
    }//end for each
    macAddress = macAddress ? macAddress : DUMMY_MAC_ADDR;
    return macAddress;
}//end getMacAddressFromMDNS

+ (nonnull NSString *)currentIPAddressOf: (nonnull NSString *)device {
    struct ifaddrs *addrs;
    NSString *ipAddress = nil;
    
    if(getifaddrs(&addrs) != 0) {
        return nil;
    }//end if
    
    //get ipv4 address
    for(struct ifaddrs *addr = addrs ; addr ; addr = addr->ifa_next) {
        if(!strcmp(addr->ifa_name, [device UTF8String])) {
            if(addr->ifa_addr) {
                struct sockaddr_in *in_addr = (struct sockaddr_in *)addr->ifa_addr;
                if(in_addr->sin_family == AF_INET) {
                    ipAddress = [self IPv4Ntop:in_addr->sin_addr.s_addr];
                    break;
                }//end if
            }//end if
        }//end if
    }//end for
    
    freeifaddrs(addrs);
    return ipAddress;
}//end currentIPAddressOf:


+ (nullable NSString *)IPv4Ntop: (in_addr_t)addr {
    char buffer[INET_ADDRSTRLEN] = {0};
    return inet_ntop(AF_INET, &addr, buffer, sizeof(buffer)) ?
    [NSString stringWithUTF8String:buffer] : nil;
}//end IPv4Ntop:

+ (in_addr_t)IPv4Pton: (nonnull NSString *)IPAddr {
    in_addr_t network = INADDR_NONE;
    return inet_pton(AF_INET, [IPAddr UTF8String], &network) == 1 ?
    network : INADDR_NONE;
}//end IPv4Pton:


+ (NSString *)getBundleId
{
    NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
    NSString *app_BundleIdentifier = [infoDictionary objectForKey:@"CFBundleIdentifier"];
    return app_BundleIdentifier;
}


+ (NSString *)getAppName
{
    NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
    NSString *appName = [infoDictionary objectForKey:@"CFBundleDisplayName"];
    return appName;
}

+ (NSNumber *)getOperator
{
    //获取本机运营商名称

    CTTelephonyNetworkInfo *info = [[CTTelephonyNetworkInfo alloc] init];

    CTCarrier *carrier = [info subscriberCellularProvider];

    //当前手机所属运营商名称

    NSString *mobile;

    //先判断有没有SIM卡，如果没有则不获取本机运营商

    if (!carrier.isoCountryCode) {

    NSLog(@"没有SIM卡");

    mobile = @"无运营商";
        return @0;

    }else{

    mobile = [carrier carrierName];

    }
    if ([mobile isEqualToString:@"中国移动"]) {
        return @1;
    }else if ([mobile isEqualToString:@"中国电信"]){
        return @2;
    }else if ([mobile isEqualToString:@"中国联通"]){
        return @3;
    }
    
    return @4;
}


+(CGFloat)getCurrentWidthResolution {
    CGFloat scale_screen = [UIScreen mainScreen].scale;
    
    CGFloat widthResolution = ScreenWidth * scale_screen;
    
    return widthResolution;
}

+(CGFloat)getCurrentHeightResolution {
    CGFloat scale_screen = [UIScreen mainScreen].scale;
    
    CGFloat heightResolution = ScreenHeight * scale_screen;
    
    return heightResolution;
}

@end
