Controller 		= window.require 'spine/controller'
Activateable	= window.require 'spine/controller/activateable'
Container 		= window.require 'spine/controller/container'

Scrollable 		= require '../../core/controller/scrollable'
Lazyloader 		= require '../../core/controller/lazyload'

Entry 			= require './entry'
NavBar 			= require './navbar'

Intent 			= (options) ->
	content = ""
	if options.colors or options.icon or options.connectButton
		content = """
			<div class=\"before\" style=\"background: #{options.colors.dark} url('#{options.icon}')\"></div><!--
		 --><div class=\"after\" style=\"background: #{options.colors.light}\">#{options.connectButton.label}</div>
		"""

	"""
	<div class=\"browser-login\">
		<div class=\"browser-login-cont\">
			<div class=\"browser-login-message\">add content from your account</div>
			<div class=\"browser-login-button\" data-content=\"#{!!content}\">#{content}</div>
		</div>
	</div>"
	"""

Controllers 	=
	folder: require './entry/folder'
	button: require './entry/button'
	image : require './entry/image'
	audio : require './entry/audio'
	video : require './entry/video'
	rss   : require './entry/rss'

class Browser extends Controller
	className: 'browser'

	@include Container
	@include Activateable
	@include Scrollable
	@include Lazyloader

	scrollOptions: {}

	events:
		'click .browser-login-button': 'auth'

	constructor: ->
		super
		# console.log("Default Browser CTR:", @Service, @title, @options)
		@service = new @Service @title, @options
		@serviceTitle or= @service.title
		
		# show how many content items the user has selected on this source
		@currentContent = []
		# @delay => @tab.count @content.length
		

		@addNavBar()
		@intent = $ Intent @service.options
		@el.addClass @title
		@el.attr 'data-filetype', @options.types[0]

		@on('activate', @auth).listenTo @service, 'auth', @onAuth
		@listenTo @nav, 'select', @setFolder
		@listenTo @nav,  'logout', @onLogout
		@listenTo @service, 'refresh', @onFolderRefresh
		@listenTo @service, 'auth-req', @_requestAuth
		@$bind 'getURL', (e, callback) => @service.getURL $(e.target).controller().item, callback

	addNavBar: ->
		@nav = new NavBar disconnectBtn: !@service.hideDisconnectBtn

	active: ->
		Activateable.active.apply @, arguments
		@scrollOptions.documentContext = @el.get(0).ownerDocument
		@scroll()
		@el.append @nav.el, @intent
		@el.append @service.faqLink if @service.faqLink?
		@refreshChildren()
		@delay =>
			@$trigger "editor:browser:active", service: @Service.name, authenticated: (@authenticated is true and @nav.el.is ':visible')

	deactivate: =>
		Activateable.deactivate.apply @, arguments
		@refreshChildren()

	###
	Auth request and event handler
	###
	auth: (e) ->
		# console.log("Default browser auth:", e)
		return if String(@el.attr 'authenticated') is 'true'
		@service.auth e?.type is 'click'

	onAuth: (@authenticated) =>
		# console.log("Default browser onAuth:", @authenticated)
		# reset lists of content
		@currentContent = []

		# show currentSource count
		if @authenticated then @updateCurrentCount() 
		# clear current content count
		else 
			@tab.count 0

		@el.attr {@authenticated}
		@setFolder @service.root if @authenticated
		@$trigger "editor:browser:auth", service: @Service.name, authenticated: (@authenticated is true)

	onLogout: =>
		@service.deauth()
		@refreshChildren()
		@currentFolder = null

	###
	Folder loading
	###
	setFolder: (entry) =>
		isSameFolder = @currentFolder?.path is entry.path
		@nav.addItem entry unless isSameFolder
		entry.children = []
		@currentFolder = entry

		@empty().$addClass 'loading'
		@service.refresh entry
		@

	refreshChildren: =>
		@children (child) -> child.refresh?()

	refresh: ->
		return if @refreshing
		@refreshing = true
		@setFolder(@currentFolder) if @currentFolder

	# update the current authenticated user's selected items count
	updateCurrentCount: =>
		# console.log("Update count:", @content, @currentContent)
		@tab.count @content.filter((a) => @currentContent.some((b) => a.id == b.id)).length

	onFolderRefresh: (children, opts = {}) =>
		# console.log("onFolderRefresh:", children, opts.root)

		# on first root folder refresh: get entire list of content update selected items count
		if opts.root
			# console.log("onFolderRefresh update count:", children, opts.root, @service)

			# reset lists of content
			rootChildren = []
			subfoldersChildren = []

			# create the list of "root subfolders files" and the list of "root files"
			children.map((child) =>
				if child.type == "folder" then subfoldersChildren = subfoldersChildren.concat(child.children.map((subChild) => @service.newEntry('audio', subChild, child.id)))
				else rootChildren.push(child)
			)
			# console.log("on Root refresh:", rootChildren, subfoldersChildren)

			# if loading subfolders children for the first time
			if subfoldersChildren.length && !@currentContent.length
				# console.log("LOAD SUBFOLDERS FILES!")
				@currentContent = @currentContent.concat(subfoldersChildren)

			# if loading files children: filter those that are already in currentContent(that are subfoldersFiles)
			if rootChildren.length
				# console.log("LOAD ROOT FILES:", rootChildren)
				children = rootChildren = rootChildren.filter((child) => !@currentContent.some((subChild) => subChild.id == child.id));
				@currentContent = @currentContent.concat(rootChildren)

			# console.log("on Root refresh:", @content, @currentContent);

			# show currentSource count
			@updateCurrentCount()

		# clear empty children in current folder
		if opts.hard then @empty().$addClass 'loading'
		
		# turn refreshing off
		@refreshing = false

		# hide loader
		@$removeClass('loading')

		# save the new children in current folder's array
		@currentFolder.children = @currentFolder.children.concat children
		# children = @children()

		# show no item icon if no children
		@el.toggleClass 'no-items', !children.length and !@children().length

		# append the new children when they are not hidden to the browser canvas
		for item in children when not /^\.[^\.]/.test item.name
			# prepare options
			opts=
				item        : item
				getPreview  : (item) => @service.preview item
				getURL      : (item, _c) => @service.getURL item, _c
				count       : @getContentItemsInFolder(item) if isFolder = item.type is 'folder'
				selected    : !!@content.filter((i)-> i.path is item.path).length unless isFolder
			# create controller
			controller = new Controllers[item.type] opts
			@append controller
			@listenTo controller, 'select', @setFolder if item.type is 'folder'

		# children.forEach (child) -> child.release()

		# update scroll and start lazy load
		@scroll().update()
		@lazyLoad()


	###
	Livecycle and activation
	###
	afterAdd: (child) ->
		Container.afterAdd.call @, child
		@listenTo child, 'active', @_active
		@listenTo child, 'activate', @_activate
		@listenTo child, 'deactivate', @_deactivate
		child

	_active: (child, options={}) =>
		@trigger 'canAdd', -> child.activate options

	# TODO: check if this is release properly
	_release: =>
		child = Container._release.apply @, arguments
		@stopListening child
		child

	_activate: (child,options) =>
		@addEntry item = child.item
		item.service = @title
		item.active = true
		item.getURLPromise = @service.getURL item, do (stat = ++item.stat)=> (url)=>
			return unless item.active and item.stat is stat
			item.url = url
			@trigger 'add', item

	_deactivate: (child,options) =>
		child.item.active = false
		@removeEntry child.item
		@trigger 'remove', child.item

	empty: ->
		child.release() for child in @children()
		@scroll().update()
		@

	addEntry: (item) ->
		itm = it for it in @content when it.path is item.path
		return if @content.indexOf(itm) isnt -1
		@content.push item
		# show currentSource count
		@updateCurrentCount()

	removeEntry: (item) ->
		itm = it for it in @content when it.path is item.path
		@content.splice @content.indexOf(itm), 1
		# show currentSource count
		@updateCurrentCount()

		for child in @children() when child.item.type in ['folder', 'button'] or child.isActive?()
			child.update @getOptions child.item

	recount: ->
		# console.log("Default Browser recount:", @children())
		child.update @getOptions child.item for child in @children()

	getOptions: (item) =>
		count:    @content.filter((i)-> !i.path.indexOf item.path ).length if isFolder = item.type is 'folder'
		selected: !!@content.filter((i)-> i.path is item.path).length unless isFolder

	whileScrolling: => @lazyLoad()

	getContentItemsInFolder: (folder) =>
		folderPath = folder.path.toLowerCase() + '/'

		@content.filter (i)->
			contentPath = i.path.toLowerCase()
			return contentPath.indexOf(folderPath) is 0
		.length

	_requestAuth: (opts) =>
		@$trigger 'content:auth-req', opts

module.exports = Browser
