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

		@service = new @Service @title, @options
		@serviceTitle or= @service.title
		@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) ->
		return if String(@el.attr 'authenticated') is 'true'
		@service.auth e?.type is 'click'

	onAuth: (@authenticated) =>
		@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

	onFolderRefresh: (children, opts = {}) =>
		if opts.hard
			@empty().$addClass 'loading'
		@refreshing = false

		@$removeClass('loading')
		@currentFolder.children = @currentFolder.children.concat children
		# children = @children()

		@el.toggleClass 'no-items', !children.length and !@children().length
		# append the child when it isnt hidden
		for item in children when not /^\.[^\.]/.test item.name
			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

			controller = new Controllers[item.type] opts
			@append controller
			@listenTo controller, 'select', @setFolder if item.type is 'folder'

		# children.forEach (child) -> child.release()
		@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
		@tab.count @content.push item

	removeEntry: (item) ->
		itm = it for it in @content when it.path is item.path
		@content.splice @content.indexOf(itm), 1
		@tab.count @content.length

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

	recount: ->
		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
