
// reference http://www.ztree.me/v3/api.php
(function ($) {

    $.fn.yinker = function (settings, action) {

        function format(template) {
            if (arguments.length > 0) {
                var args = Array.prototype.slice.call(arguments, 1);

                return template.replace(/\{(\d+)\}/g, function (m, i) {
                    return args[i];
                });
            }
            return null;
        }

        function Tree() {
            this.id = 'yinker';
            this.op = 'init';
            this.checkbox = false;
            this.autoOpen = false;
            this.nodes = [];
        }

        Tree.bind = function (data, parent, isTop) {
            var nodes = data.nodes;

            for (var i = 0, len = nodes.length; i < len; i++) {
                var node = nodes[i];
                var newNode = $.extend(new Node(), {
                    autoOpen: data.autoOpen,
                    checkbox: data.checkbox
                }, node);

                var hasChild = $.isArray(node.nodes);
                var first = i == 0;
                var last = (i == len - 1);
                var sibling = len == 1;

                // 附加其他
                node.id = parent.attr('id') + '_' + i;
                node.autoOpen = node.autoOpen || data.autoOpen;
                node.checkbox = node.checkbox || data.checkbox;

                // 样式
                newNode.id = node.id;
                newNode.nodeNum = hasChild ? node.nodes.length : 0;
                newNode.style(hasChild, isTop, first, last, sibling);

                var nodeView = new NodeView(newNode, parent, sibling || last);

                if (hasChild) {
                    Tree.bind(node, nodeView.child, false);
                }
            }
        }

        Tree.onclick = function (e) {
            e = window.event || e;

            var target = e.srcElement || e.target;

            switch (target.tagName) {
                case 'A':
                    container.find('.selected').removeClass('selected');
                    $(target).addClass('selected');
                    break;

                case 'EM':
                    container.find('.selected').removeClass('selected');
                    $(target).parent().addClass('selected');
                    break;

                case 'SPAN':
                    if (target.className == 'text') {
                        $(target).prev().click();
                    } else {
                        Node.prototype.expand.call(target);
                    }
                    break;

                case 'INPUT':
                    var checked = target.checked;
                    var checkboxs = $(target).parent().next().find('input:checkbox');
                    var len = checkboxs.length;

                    if (len >= 50) {
                        var i = 0, timerId = window.setInterval(function () {
                            if (i < len) {
                                $(checkboxs[i]).attr('checked', checked);
                            } else {
                                window.clearInterval(timerId);
                            }
                            i++;
                        }, 0);
                    } else {
                        checkboxs.attr('checked', checked);
                    }
                    break;

                default: break;
            }

            if (window.event) {
                e.cancelBubble = true;
            } else {
                e.stopPropagation();
            }
        }

        Tree.ondblclick = function (e) {
            e = window.event || e;

            var target = e.srcElement || e.target;

            if (target.tagName == 'A') {
                $(target).parent().prev().click();
            }

            if (window.event) {
                e.cancelBubble = true;
            } else {
                e.stopPropagation();
            }
        }

        Tree.update = function () {
            var selectedNode = container.find('#' + context.id + '>ul');

            Tree.bind(context.nodes, selectedNode, 1);
        }

        Tree.remove = function () {
            container.find('#' + context.id + '>ul').hide();
        }

        Tree.init = function () {
            var tree = $('<ul class="yinker" />');

            if (context.width) {
                tree.css({
                    'overflow-x': 'auto',
                    'width': context.width
                });
            }

            if (context.height) {
                tree.css({
                    'overflow-y': 'auto',
                    'height': context.height
                });
            }

            tree.attr('id', context.id).appendTo(container);
            tree.bind('click', Tree.onclick).bind('dblclick', Tree.ondblclick);

            Tree.bind(context, tree, 1);
        }

        function Node() {
            /* events */
            this.click = null;
            this.dblclick = null;
            this.remove = null;
            this.check = null;

            /* attrs */
            this.autoOpen = false;
            this.checkbox = false;
            this.name = '';
            this.titile = '';
            this.icon = '../style/default/img/icon_online.png';
            this.href = '';
            this.nodes = [];
            this.nodeNum = 0;
        }

        Node.prototype.style = function (hasChild, top, first, last, sibling) {
            /// <summary>
            /// 
            /// </summary>
            /// <param name="hasChild">有没有子节点</param>
            /// <param name="top">是否是根节点</param>
            /// <param name="first">是不是第一个节点（同父节点）</param>
            /// <param name="last">是不是最后一个节点（同父节点）</param>
            /// <param name="sibling">有没有兄弟节点</param>
            if (hasChild === true || top === true) {
                if (sibling === true) {
                    this.indentClass = 'indent-root_close';
                } else {
                    if (first === true) {
                        this.indentClass = 'indent-roots_close';
                    } else if (last === true) {
                        this.indentClass = 'indent-bottom_close';
                    } else {
                        this.indentClass = 'indent-center_close';
                    }
                }
                if (this.autoOpen) {
                    this.indentClass = this.indentClass.replace('_close', '_open');
                }
            } else {
                if (sibling === true) {
                    this.indentClass = 'indent-root_docu';
                } else {
                    if (last === true) {
                        this.indentClass = 'indent-bottom_docu';
                    } else {
                        this.indentClass = 'indent-center_docu';
                    }
                }
            }
        }

        Node.prototype.expand = function () {
            var _this = $(this);
            var className = _this.attr('class');

            switch (className) {
                case 'indent-root_open': className = 'indent-root_close'; break;
                case 'indent-root_close': className = 'indent-root_open'; break;
                case 'indent-roots_open': className = 'indent-roots_close'; break;
                case 'indent-roots_close': className = 'indent-roots_open'; break;
                case 'indent-center_open': className = 'indent-center_close'; break;
                case 'indent-center_close': className = 'indent-center_open'; break;
                case 'indent-bottom_open': className = 'indent-bottom_close'; break;
                case 'indent-bottom_close': className = 'indent-bottom_open'; break;
                case 'indent-noline_open': className = 'indent-noline_close'; break;
                case 'indent-noline_close': className = 'indent-noline_open'; break;
                default: break;
            }

            _this.attr('class', className);
            _this.parent().children('ul').toggle();
        }

        function NodeView(settings, parent, edge) {
            var nodeHTML = '<li class="node" id="{0}"><span class="{1}"></span>' +
                '<span class="text" title="{2}">{7}<img src="{3}">' +
                '<a{4}>{5}<em>({6})</em></a></span>';

            nodeHTML = format(nodeHTML,
                settings.id,
                settings.indentClass,
                settings.title,
                settings.icon,
                settings.href ? ' href="' + settings.href + '"' : '',
                settings.name,
                settings.nodeNum,
                settings.checkbox ? '<input type="checkbox">' : '');

            parent.append(nodeHTML);

            this.node = parent.children('li:last');

            if (settings.click) {
                this.node.bind('click', settings.click);
            }

            if ($.isArray(settings.nodes)) {
                var childId = settings.id + '_ul';
                var childClass = edge === true ? 'unline' : 'line';
                var childHTML = '<ul id="{0}" class="{1}" />';

                childHTML = format(childHTML, childId, childClass);

                this.child = $(childHTML);
                this.child.appendTo(this.node);

                if (settings.autoOpen) {
                    this.child.show();
                }
            }
        }

        NodeView.prototype.increase = function () {
            var num = this.desc.text();
            num++;
            this.desc.text('(' + num + ')');
        }


        var container = this;
        var context = $.extend(new Tree(), settings);

        console.log(new Date().getSeconds());
        Tree[context.op]();
        console.log(new Date().getSeconds());
        return this;
    };

})(window.jQuery);