
Model  	= window.require 'spine/model'
Skin   	= require './skin'
AjaxMixin   = require '../../api/mixin'

_loadSkins = (widget) ->
	if widget.hasAllSkins
		Skin.refresh(widget.skins)
		return widget
	else
		return Skin.ajaxFetch({widget_id: widget.id}).then (data) ->
			Skin.refresh(data)
			widget.updateAttribute('hasAllSkins', true)
			return widget

hasRequiredFields = (w, fields) ->
	for field in fields
		return false unless w[field]
	return true

class Widget extends Model
	@extend AjaxMixin
	@configure(
		'Widget',
		'name',
		'module',
		'category',
		'slug',
		'skinMeta',
		'contentMeta'
		'skins',
		'content',
		'css',
		'js',
		'width',
		'height',
		# added so subsequent loads will use the cached skins
		# a cleaner solution should be found
		'hasAllSkins'
	)

	@current: null

	# Loads a widget from memory or by ajax
	#
	# The local collection is searched first and if it's not found,
	# it's fetched from ajax.
	#
	# You can send an array into options.fields to define required
	# fields. If the locally stored widget does not have the fields
	# a full ajax refresh is performed.
	#
	# TODO: partial refresh with only required fields
	#
	# @param string	id		the id of the widget
	# @param object	options
	# @return promise
	@load: (id, options) ->
		fields = options?.fields

		hasLoaded = Blogvio.Aye.defer()

		process = Blogvio.Aye.defer()
		process.promise
			.then(_loadSkins)
			.fail(hasLoaded.reject)
			.then(hasLoaded.resolve)

		try
			w = Widget.find(id)

			if fields and !hasRequiredFields(w, fields)
				throw new Error("Widget[#{ id }] does not have all required fields: #{ fields }")

			process.resolve(w)
		catch e
			console.warn(e)
			@ajax()
				.fetch({id})
				.then((widgets) -> widgets[0])
				.then(process.resolve)
				.fail(process.reject)

		return hasLoaded.promise

	getSkins: -> Skin.findAllByAttribute('widget_id', @id)

module.exports = Widget
