/*
 * TreeList Widget
 *
 * Supported options:
 *  - handle - class name to use as a handle
 *  - nested - set to false if sorting should be kept within each OL container, if using
 *             a handle it should be focused enough to exclude nested handles.
 *
 * Events:
 * - move.oc.treelist - triggered when a node on the tree is moved.
 *
 * Dependencies:
 * - Sortable Plugin (october.sortable.js)
 */
+function ($) { "use strict";
    var Base = $.oc.foundation.base,
        BaseProto = Base.prototype

    var TreeListWidget = function (element, options) {
        this.$el = $(element)
        this.options = options || {};

        Base.call(this)

        $.oc.foundation.controlUtils.markDisposable(element)
        this.init()
    }

    TreeListWidget.prototype = Object.create(BaseProto)
    TreeListWidget.prototype.constructor = TreeListWidget

    TreeListWidget.prototype.init = function() {
        var sortableOptions = {
                handle: this.options.handle,
                nested: this.options.nested,
                onDrop: this.proxy(this.onDrop),
                afterMove: this.proxy(this.onAfterMove)
            }

        this.$el.find('> ol').sortable($.extend(sortableOptions, this.options))

        if (!this.options.nested)
            this.$el.find('> ol ol').sortable($.extend(sortableOptions, this.options))

        this.$el.one('dispose-control', this.proxy(this.dispose))
    }

    TreeListWidget.prototype.dispose = function() {
        this.unbind()
        BaseProto.dispose.call(this)
    }

    TreeListWidget.prototype.unbind = function() {
        this.$el.off('dispose-control', this.proxy(this.dispose))

        this.$el.find('> ol').sortable('destroy')

        if (!this.options.nested) {
            this.$el.find('> ol ol').sortable('destroy')
        }

        this.$el.removeData('oc.treelist')

        this.$el = null
        this.options = null
    }

    TreeListWidget.DEFAULTS = {
        handle: null,
        nested: true
    }

    // TREELIST EVENT HANDLERS
    // ============================

    TreeListWidget.prototype.onDrop = function($item, container, _super) {
        // The event handler could be registered after the
        // sortable is destroyed. This should be fixed later.
        if (!this.$el) {
            return
        }

        this.$el.trigger('move.oc.treelist', { item: $item, container: container })
        _super($item, container)
    }

    TreeListWidget.prototype.onAfterMove = function($placeholder, container, $closestEl) {
        if (!this.$el) {
            return
        }

        this.$el.trigger('aftermove.oc.treelist', { placeholder: $placeholder, container: container, closestEl: $closestEl })
    }

    // TREELIST WIDGET PLUGIN DEFINITION
    // ============================

    var old = $.fn.treeListWidget

    $.fn.treeListWidget = function (option) {
        var args = arguments,
            result

        this.each(function () {
            var $this   = $(this)
            var data    = $this.data('oc.treelist')
            var options = $.extend({}, TreeListWidget.DEFAULTS, $this.data(), typeof option == 'object' && option)
            if (!data) $this.data('oc.treelist', (data = new TreeListWidget(this, options)))
            if (typeof option == 'string') result = data[option].call(data)
            if (typeof result != 'undefined') return false
        })

        return result ? result : this
      }

    $.fn.treeListWidget.Constructor = TreeListWidget

    // TREELIST WIDGET NO CONFLICT
    // =================

    $.fn.treeListWidget.noConflict = function () {
        $.fn.treeListWidget = old
        return this
    }

    // TREELIST WIDGET DATA-API
    // ==============

    $(document).render(function(){
        $('[data-control="treelist"]').treeListWidget();
    })

}(window.jQuery);