/*!
 * Copyright 2017 Vpn.Email Canada Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


import * as Https from 'https'
import * as Http from 'http'
import * as Net from 'net'
import * as Url from 'url'
import * as Os from 'os'
import * as Ip from 'ip'
import * as Async from 'async'
const url = 'https://geoip.nekudo.com/api'
const url1 = 'http://v6.ipv6-test.com/api/myip.php'
const url2 = 'http://v4v6.ipv6-test.com/api/myip.php'

export interface result {
	city: string;
	country: {
		name: string;
		code: string;
	}
	location: {
		accuracy_radius: number;
		latitude: number;
		longitude: number;
		time_zone: string;

	}
	ip: string;
}

export interface ipAddress {
	PrivateIp4: { address: string, network: Ip.network } [];
	PrivateIp6: string;
	PublicIp4: string;
	publicIp6: string;
}

const connect = ( _url: string, CallBack ) => {
	const _CallBack = ( res ) => {
		res.on ( 'data', ( data: Buffer ) => {
			try {
				const ret = JSON.parse ( data.toString ('utf8'))
				return CallBack ( null, ret )
			} catch ( ex ) {
				return CallBack ( null, data.toString ('utf8'))
			}
		})
	}
	const uu = Url.parse ( _url )
	if ( /^https:/i.test ( _url ))
		 
		return  Https.get ( _url, _CallBack ). on ( 'error', err => {
			return CallBack ( err )
		}) 
	return Http.get ( _url, _CallBack ). on ( 'error', err => {
		return CallBack ( err )
	}) 
}

export const dekudo = ( CallBack: ( err?: Error, data?: { network: boolean, ipv4: string, ipv6: string }) => void ) => {
	const ret = {
		network: false,
		ipv4: null,
		ipv6: null
	}
	const reqult = ( data ) => {
		ret.network = true
		const ip = Net.isIP ( data )
		if ( !ip ) {
			if ( data.ip && data.ip.length ) {
				ret.ipv4 = data.ip
			}
			return
		}
		if ( ip === 4 )
			ret.ipv4 = data
		else
			ret.ipv6 = data
		return
	}
	connect ( url1, ( err, data ) => {

		if ( data )
			reqult ( data )
		return connect ( url2, ( err1, data1: result ) => {
			if ( err1 ) {
				return CallBack ( null, ret )
			}
			reqult ( data1 )
			return CallBack ( null, ret )
		})
	})
	
}

export const localNetInterFace: () => ipAddress = () => {
	const ret: ipAddress = {
		PrivateIp4:[],
		PrivateIp6: null,
		PublicIp4: null,
		publicIp6: null,
	}
	const _interface = Os.networkInterfaces ()
	const keys = Object.keys( _interface )
	keys.forEach ( n => {
		
			const ip = _interface [n]
			for ( let i = 0; i < ip.length; i ++ ) {
				const _ip = ip[i]
				const _ipF = Net.isIP (_ip.address )
				if ( _ip.internal )
					continue
				if ( Ip.isPrivate ( _ip.address )) {
					if ( _ipF === 4 ) {
						ret.PrivateIp4.push ( { network: Ip.subnet ( _ip.address, _ip.netmask ), address: _ip.address} )
						continue
					}
					ret.PrivateIp6 = _ip.address
					continue
				}
				if ( _ipF === 4 ) {
					ret.PublicIp4 =  _ip.address
					continue
				}
				ret.publicIp6 = _ip.address
			}
	})

	return ret
}

export const getLocalNetWorkIp = ( localNetworkPool: { network: Ip.network, address: string }[], ipAddress: string ) => {
	const local = localNetworkPool.find ( n => {
		return n.network.contains ( ipAddress )
	})
	return local ? local.address : localNetworkPool[0].address

}