ProviderBase = require './ProviderBase'
freebase = require 'freebase'
async = require 'async'
_ = require 'underscore'

class Freebase extends ProviderBase
	constructor: (@data, @freebase = require('freebase'), @defaults = {}, @request_concurrency = 4, @request_wait_time = 1) -> 
		if process.env.GOOGLE_API_KEY
			@defaults['key'] = process.env.GOOGLE_API_KEY
		@internal_queue = async.queue(((item, callback) =>  
			property = item.property
			key = item.key
			data = item.data
			defaults = item.defaults
			freebase = item.freebase

			if @internal_object[property]
				additonal = {}
				additonal[key] = @internal_object[property]

				callback null, additonal
				return

			async.waterfall [
				(next) =>
					if data['freebase_id']
						next null, data['freebase_id']
					else
						freebase.search (data.freebase_id or data.title ), _.extend({ type: "/cvg/computer_videogame" }, defaults), (result) =>
							if result and result.length
								next null, result.shift().mid
							else
								next 'no results found'
				,(mid, next) =>
					additonal = {}
					freebase.question (mid), _.extend({ property: property }, defaults), (answer) =>
						if !answer || !answer.length
							additonal[key] = null
						else if answer.length == 1
							additonal[key] = answer.shift().text
						else
							additonal[key] = answer.map (x) -> x.text
						next null, additonal
				,(data, next) =>
					setTimeout (data) =>
						next null, data
					,item.options.request_wait_time,data
			], callback
		),@request_concurrency)
		@internal_object = {}
		@internal_queue.pause()
		@all(@internal_queue.resume)

	internal_queue: null

	all: (callback) ->
		async.waterfall [
			($next) =>
				@freebase.all_data (@data['freebase_id'] or @data['title']), _.extend({ type: "/cvg/computer_videogame" }, @defaults), (result) =>
					if result.property
						async.map Object.keys(result.property), (prop, next) =>
							if result.property[prop].values.length > 1
								next null, { key: prop, value: result.property[prop].values.map((x) -> (x.text or x)) }
							else if result.property[prop].values.length
								next null, { key: prop, value: result.property[prop].values.shift().text }
							else
								next null, { key: prop, value: [] }
						,(e, props) =>
							async.each props, (obj, next) =>
								@internal_object[obj.key] = obj.value
								next()
							,$next
					else 
						$next()
		],callback


	property: (property, key, callback) ->
		@internal_queue.push 
			property: property
			key: key
			data: @data
			defaults: @defaults
			freebase: @freebase
			internal_object: @internal_object
			options: 
				request_concurrency: @request_concurrency
				request_wait_time: @request_wait_time
		,(E, data) =>
			callback E, data


	freebase_id: (args, callback) ->
		@property('/type/object/mid', 'freebase_id', callback)

	title: (args, callback) -> 
		@property('/type/object/name', 'title', callback)

	description: (args, callback) ->
		@property('/common/topic/description', 'description', callback)

	cover_art: (args, callback) ->
		additonal = {}
		@freebase_id [], (E, mid) =>
			if (!@data.freebase_id and !(mid))
				callback null, additonal
			else
				@freebase.image (@data.freebase_id or (if mid then mid.freebase_id else null)),  _.extend({}, @defaults),(image) =>
					additonal['cover_art'] = image
					callback null, additonal

	platforms: (args, callback) ->
		additonal = {}
		@freebase_id [], (E, mid) =>
			if (!mid)
				callback null, additonal
			else
				@freebase.question (if mid then mid.freebase_id else null), _.extend({ property: '/cvg/computer_videogame/versions' }, @defaults), (vers) =>
					async.concat vers, (ver, next) => 
						@freebase.question ver.id, _.extend({ property: '/cvg/game_version/platform' }, @defaults), (data) =>
							next null, data.map (x) -> x.text
					,(E, platforms) =>
						additonal['platforms'] = platforms
						callback null, additonal

	genres: (args, callback) -> 
		@property('/cvg/computer_videogame/cvg_genre', 'genres', callback)

	series: (args, callback) ->
		@property('/cvg/computer_videogame/game_series', 'series', callback)

	developer: (args, callback) ->
		@property('/cvg/computer_videogame/developer', 'developer', callback)

	publisher: (args, callback) ->
		@property('/cvg/computer_videogame/publisher', 'publisher', callback)

	gameplay_modes: (args, callback) ->
		@property('/cvg/computer_videogame/gameplay_modes', 'gameplay_modes', (E, data) =>
			console.log data
			#if data and data.gameplay_modes
				
			callback(E, data)
		)

	release_date: (args, callback) ->
		@property('/cvg/computer_videogame/release_date', 'release_date', (E, data) =>
			if data and data.release_date
				data.release_date = new Date data.release_date
			callback(E, data)
		)

module.exports = Freebase