console = window.require 'spine/utils/console'
Service = require '../../../browser/model'
Entry   = require '../../../browser/model/entry'

SharePopup  = require './share-popup'

showShareSettingsPost = (link) ->
	return !(@onActivate = null) if !@isPrivate
	return !SharePopup.setLink(link).pop $ 'body'

cache = do ->
	_namespace = 'e_gd_c'
	_cache_exp = 10000#cache expires after 10s
	# _cache = JSON.parse localStorage.getItem(_namespace) or '{}'
	_cache = {}
	init: (namespace, cache_exp) ->
		_namespace = namespace
		_cache_exp = cache_exp
	clear: (prefix, id) ->
		return _cache[prefix] = {} unless id
		_cache[prefix]?[id] = null
	set: (prefix, id, value) ->
		(_cache[prefix] or= {})[id] = value
		_cache[prefix][id].__exp__ = +new Date + _cache_exp
		# localStorage.setItem _namespace, JSON.stringify _cache
	check: (prefix, id) ->
		_cache[prefix]?[id]?.__exp__ > +new Date
	get: (prefix, id) ->
		_cache[prefix]?[id]

class GoogleDriveService extends Service
	scope: 'https://www.googleapis.com/auth/drive.readonly'
	constructor: ->
		super
		@title = 'Google Drive'
		@type = 'image' if ~@options.types.indexOf 'image'
		@type = 'video' if ~@options.types.indexOf 'video'
		@type = 'audio' if ~@options.types.indexOf 'audio'
		@root.id = 'root'
		@authenticated = false

	_auth: (interactive=true) ->
		gapi.auth.authorize
			client_id: gapi.client.id
			scope: @scope
			immediate: !interactive
		, @onAuth

	onAuth: (result) =>
		if !result.status.signed_in or result.error? or !~result.scope.indexOf @scope
			return @trigger 'auth', @authenticated = false

		gapi.client.load 'drive', 'v2', @driveReady

	driveReady: =>
		@trigger 'auth', @authenticated = true

	refresh: (entry) =>
		@entry = entry

		onResponse = =>
			@gotResponse entry.id, arguments...

		@getDriverData entry, onResponse

	getDriverData: (entry, callback) =>
		@getDriverFolders(entry.id, callback).then =>
			@getDriverFiles(entry.id, @type, callback).then callback.bind @, [], true

	gotResponse: (folderID, data, triggerEmpty) =>
		return unless @entry.id is folderID
		entries = (data.items or []).map (item) =>
			return unless item
			type = item.mimeType.match(/image|video|folder|audio/)[0]
			new Entry
				id: item.id
				type: type
				path: @entry.path+'/'+item.title
				name: item.title
				preview: item.thumbnailLink?.replace /s\d+$/, 's250'
				url: "https://drive.google.com/uc?id=#{item.id}&export=download"
				parent: item.parents[0].id
				isPrivate: isPrivate = !item.permissions.filter((perm) -> perm.id is 'anyone').length
				order: 0.5*(type is 'folder') + parseFloat '0.'+(new Date(item.createdDate).getTime())
				webLink: item.alternateLink
				onActivate: if isPrivate then ->
					# check for updated permissions
					$(window).one 'focus', onFocus = =>
						# read 2 times, apparently google returns a cached version the first time
						gapi.client.drive.permissions.list(fileId: @id).execute =>
							gapi.client.drive.permissions.list(fileId: @id).execute (data) =>
								@isPrivate = !data.items.filter((perm) -> perm.id is 'anyone').length
								@trigger 'refresh'
					showShareSettingsPost.call @, @webLink
		.filter((item)->!!(item and item.id)).sort (a, b) -> -(a.order - b.order)

		@trigger 'refresh', entries if entries.length
		@trigger 'refresh', [] if triggerEmpty and !@entry.children.length

	checkEmpty: =>
		@trigger 'refresh', []

	getURL: (entry, callback) ->
		callback entry.url

	preview: (entry)-> entry.preview

	deauth: ->
		@trigger 'auth', @authenticated = false

	getDriverFolders: (folderID, callback) =>
		@getDriverFiles folderID, 'folder', callback

	getDriverFiles: (folderID, type, callback) =>
		def = new $.Deferred

		do req = (nextPageToken = null) =>
			@requestDriverFiles(folderID, type, nextPageToken).then (resp) =>
				callback resp
				if resp.nextPageToken
					if @entry.id is folderID and entry = @entry.children.slice(-1)[0]
						entry.onShow = (-> req resp.nextPageToken; @onShow = ->).bind entry
					return
				def.resolve()

		def.promise()

	requestDriverFiles: (folderID, fileType, pageToken) =>
		def = new $.Deferred

		if cachedResponse = cache.get folderID, pageToken or fileType
			def.resolve cachedResponse

		# fetch only if cache has expired
		unless cache.check folderID, pageToken or fileType
			gapi.client.drive.files.list
				q: @createQuery folderID, fileType
				fields: 'items(id,title,mimeType,thumbnailLink,createdDate,permissions(id),parents(id),alternateLink),nextPageToken'
				pageToken: pageToken
			.execute (data) =>
				delete data.result if data.result?
				cache.set folderID, pageToken or fileType, data
				def.resolve data

		def.promise()

	createQuery: (id, type, date)=>
		mimeType = "mimeType contains \'#{type}/\'"
		mimeType = 'mimeType=\'application/vnd.google-apps.folder\'' if type is 'folder'

		q = "trashed=false and (#{mimeType}) and \'#{id}\' in parents"
		q += " and modifiedDate > \'#{date}\'" if date
		q

module.exports = GoogleDriveService
