Async = require 'async'
_ = require 'lodash'

Cache = require './cache'

handlers = []
handlers.push(require('./handlers/geoiptool'))
handlers.push(require('./handlers/ipapi'))

class Geoip
	constructor: () ->
		@configure()

	configure: (options = {}) ->
		options = _.defaults options,
			useCache: true
			cacheMax: 500

		@cache = if options.useCache then new Cache({ max: options.cacheMax }) else null

	lookup: (ip, callback) ->
		@cache.get ip, (err, cache) =>
			return callback(null, cache.data, cache.info) if cache

			Async.map handlers
				, (handler, done) ->
					handler.lookup ip, (err, data, info) ->
						done(err, {
							data: data
							info: info
						})

				, (err, items) =>
					return callback(err) if err

					for item in items
						item.rating = @rate(@clean(item.data))
						item.time = item.info.time

					items = _.sortByOrder items, ['rating', 'time'], [false, true]

					@cache.set(items[0])

					callback(null, items[0].data, items[0].info)

	clean: (data) ->
		data.country.name = data.country.name.trim() if data.country.name
		data.country.code = data.country.code.trim() if data.country.code
		data.region = data.region.trim() if data.region
		data.city = data.city.trim() if data.city

		return data

	rate: (data) ->
		score = 0

		score += 3 if data.country.name
		score += 1 if data.country.code
		score += 1 if data.region
		score += 3 if data.city

		return score

	result: (data, info, callback) ->
		data = @clean(data)
		rating = @rate(data)

		@cache.set {
			data: data
			info: info
			time: info.time
			rating: @rate(data)
		}

		callback(null, data, info)

module.exports = new Geoip