Model = window.require 'spine/model'
Helper      = window.require 'spine/utils/helper'
isArray     = Helper.isArray
defaultAtts = ['order', 'metadata', 'composition_id', '_isDemoContent']
class Content extends Model
	@records:[]
	@irecords:{}
	@crecords:{}
	@configure 'Content'

	###
	Sort function used to sort items
	###
	@comparator:(a,b)->(a.order or a.id) - (b.order or b.id)

	constructor:(atts={})->
		throw new Error('Content must be associated to a composition.') unless atts.composition_id
		@composition_id = atts.composition_id
		@_meta = atts._meta
		for attr of (mattr = @meta().attributes) when (!atts[attr]? and mattr[attr]?)
			atts[attr] = mattr[attr].options.default
		super(atts)
		@id or= @cid

	meta: ->
		@_meta or= @composition().contentMeta()

	composition: ->
		(require './composition').find(@composition_id)

	attributes: ->
		attributes = defaultAtts.slice(0) # make a clone of the defaultAtts
		meta_attributes = (attribute for attribute, options of @meta().attributes)
		attributes.push meta_attributes...

		result = {}
		for key in attributes when key of this
			if typeof @[key] is 'function'
				result[key] = @[key]()
			else
				result[key] = @[key]
		result.id = @id if @id
		result._meta = @_meta if @_meta
		result

	_metadata: (key, value, options = {}) =>
		# return all metadata if call is ` _metadata()`
		return @metadata or= {} unless key?
		# return key metadata if called with `_metadata(key)`
		return @_metadata()[key] unless value?

		# set key metadata to value if called with `_metadata(key, value)`
		# skip update if same value
		return @_metadata()[key] if @_metadata()[key] is value
		@_metadata()[key] = value
		options.attribute = 'metadata'
		@updateAttribute 'metadata', @metadata, options

	editedMeta: (attr, set) =>
		return @_metadata('edited') or [] unless attr?
		return 1+@editedMeta().indexOf attr if attr and !set?
		return unless attr and set?

		editedMeta = @editedMeta().concat(attr).filter (f) => set or f isnt attr
		@_metadata 'edited', editedMeta

	attrMeta: (attr, value, options) =>
		return @_metadata('attr_meta') or {} unless attr?
		return @attrMeta()[attr] if attr? and !value?
		if attr? and value?
			(attr_meta = @attrMeta())[attr] = value
			@_metadata 'attr_meta', attr_meta, options

	toJSON: ->
		result = super
		delete result._meta
		return result

module.exports = Content
