'use strict';

var clear          = require('es5-ext/array/#/clear')
  , assign         = require('es5-ext/object/assign')
  , Set            = require('es6-set')
  , d              = require('d')
  , autoBind       = require('d/auto-bind')
  , lazy           = require('d/lazy')
  , memoizeMethods = require('memoizee/methods-plain')
  , replaceContent = require('dom-ext/element/#/replace-content')
  , DOMCheckbox    = require('../_controls/checkbox')
  , DOMInput       = require('./')

  , map = Array.prototype.map
  , notSupported = function () { throw new Error('Not supported'); }

  , DOMMultiple;

module.exports = DOMMultiple = function (document, type/*, options*/) {
	DOMInput.apply(this, arguments);
	this.allItems = [];
	this.reload();
};

DOMMultiple.prototype = Object.create(DOMInput.prototype, assign({
	constructor: d(DOMMultiple),
	onChange: d(function () {
		var value, changed, valid, emitChanged, emitValid;
		value = this.value;
		changed = this.items.some(function (item) { return item.changed; });
		valid = this.required ? Boolean(value.length) : true;

		if (this.changed !== changed) {
			this.changed = changed;
			emitChanged = true;
		}
		if (this.valid !== valid) {
			this.valid = valid;
			emitValid = true;
		}

		this.emit('change', value);
		if (emitChanged) this.emit('change:changed', this.changed);
		if (emitValid) this.emit('change:valid', this.valid);
	}),
	inputValue: d.gs(function () {
		return this.items.map(function (item) { return item.value; })
			.filter(Boolean);
	}, function (value) {
		if (value == null) value = new Set();
		this._value = value;
		this.allItems.forEach(function (item) {
			var obj = this.type.fromInputValue(item.control.value);
			item.value = value.has(obj) ? obj : null;
		}, this);
		this.onChange();
	}),
	_render: d(function () {
		this.dom = this.document.createElement('ul');
		this.dom.className = 'dbjs multiple';
	}),
	safeRemoveItem: d(notSupported),
	addItem: d(notSupported),
	removeItem: d(notSupported)
}, lazy({
	markEmpty: d(function () {
		return this.make('input', { type: 'hidden', value: '', name: this.name });
	})
}), autoBind({
	reload: d(function () {
		clear.call(this.items);
		replaceContent.call(this.dom, map.call(this.dbList, function (item) {
			var data = this.renderItem(item.value, item.label);
			this.items.push(data.input);
			return data.dom;
		}, this), this.markEmpty);
		this.items.push(this.markEmpty);
	})
}), memoizeMethods({
	renderItem: d(function (value, label) {
		var el = this.make, input, dom;
		input = new DOMCheckbox(this.document, this.type, this.options);
		dom = el('li', el('label', input, ' ', label));

		if (this.name) input.name = this.name;
		input.parent = this;
		input.listItem = dom;
		input.control.setAttribute('value', value);
		input.on('change', this.onChange);
		this.allItems.push(input);
		return { dom: dom, input: input };
	})
})));

@@ -112,24 +112,89 @@
 ct/assign')%0A
+  , normalizeOpts  = require('es5-ext/object/normalize-options')%0A
   , Set     
@@ -739,16 +739,53 @@
 ns*/) %7B%0A
+%09var options = Object(arguments%5B2%5D);%0A
 %09DOMInpu
@@ -790,28 +790,84 @@
 put.
-apply
+call
 (this, 
-arg
+doc
 ument
+, type, options);%0A%09this.itemOptions = Object(options.item
 s);%0A
@@ -2670,24 +2670,143 @@
 , input, dom
+, options;%0A%09%09options = this.itemOptions%5Bvalue%5D%0A%09%09%09? normalizeOpts(this.options, this.itemOptions%5Bvalue%5D) : this.options
 ;%0A%09%09input = 
@@ -2847,21 +2847,16 @@
 s.type, 
-this.
 options)

Support item specific options in multiple checkbox