(function($, document, window){
    'use strict';
    var EVENT_SEND_SUCCESS = "EASYEDIT_SEND_SUCCESS"
    function EasyEditor( element, options ){
        this.elem = element;
        options = options || {};
        this.className = options.className || 'easyeditor';

        // 'bold', 'italic', 'link', 'h2', 'h3', 'h4', 'alignleft', 'aligncenter', 'alignright', 'quote', 'code', 'list', 'x'
        var defaultButtons = ['bold', 'italic', 'link', 'h2', 'h3', 'h4', 'alignleft', 'aligncenter', 'alignright'];
        this.buttons = options.buttons || defaultButtons;
        this.buttonsHtml = options.buttonsHtml || null;
        this.overwriteButtonSettings = options.overwriteButtonSettings || null;
        this.css = options.css || null;
        this.onLoaded = typeof options.onLoaded === 'function' ? options.onLoaded : null;
        this.randomString = Math.random().toString(36).substring(7);
        this.theme = options.theme || null;
        this.dropdown = options.dropdown || {};
        this.height = options.height || {};
        this.imageSetting = options.imageSetting || {};
        this.imageSetting = $.extend(this.imageSetting, {watermark:false});

        this.attachEvents();
    }

    // initialize
    EasyEditor.prototype.attachEvents = function() {
        this.bootstrap();
        this.addToolbar();
        this.handleKeypress();
        this.handleResizeImage();
        this.utils();

        if(this.onLoaded !== null) {
            this.onLoaded.call(this);
        }
    };

    // Adding necessary classes and attributes in editor
    EasyEditor.prototype.bootstrap = function() {
        var _this = this;
        var tag = $(_this.elem).prop('tagName').toLowerCase();

        if(tag === 'textarea' || tag === 'input') {
            var placeholderText = $(_this.elem).attr('placeholder') || '';

            var marginTop = $(_this.elem).css('marginTop') || 0;
            var marginBottom = $(_this.elem).css('marginBottom') || 0;
            var style = '';
            if(marginTop.length > 0 || marginBottom.length > 0) {
                style = ' style="margin-top: ' + marginTop + '; margin-bottom: ' + marginBottom + '" ';
            }

            $(_this.elem).after('<div id="' + _this.randomString + '-editor" placeholder="' + placeholderText + '">' + $(_this.elem).val() + '</div>');
            $(_this.elem).hide().addClass(_this.randomString + '-bind');
            if(_this.height){
                $(_this.elem).css("height",_this.height);
            }
            if(_this.addCls){
                $(_this.elem).addClass(_this.addCls);
            }
            _this.elem = document.getElementById(_this.randomString + '-editor');
            $(_this.elem).attr('contentEditable', true).addClass(_this.className).wrap('<div class="'+ _this.className +'-wrapper"' + style + '></div>');
        }
        else {
            $(_this.elem).attr('contentEditable', true).addClass(_this.className).wrap('<div class="'+ _this.className +'-wrapper"></div>');
        }

        this.$wrapperElem = $(_this.elem).parent();

        if(_this.css !== null) {
            $(_this.elem).css(_this.css);
        }

        this.containerClass = '.' + _this.className +'-wrapper';

        if(typeof _this.elem === 'string') {
            _this.elem = $(_this.elem).get(0);
        }

        if(_this.theme !== null) {
            $(_this.elem).closest(_this.containerClass).addClass(_this.theme);
        }
    };

    // enter and paste key handler
    EasyEditor.prototype.handleKeypress = function(){
        var _this = this;

        $(_this.elem).keydown(function(e) {
            if(e.keyCode === 13 && _this.isSelectionInsideElement('li') === false) {
                e.preventDefault();

                if(e.shiftKey === true) {
                    document.execCommand('insertHTML', false, '<br>');
                }
                else {
                    document.execCommand('insertHTML', false, '<br><br>');
                }

                return false;
            }
        });

        _this.elem.addEventListener('paste', function(e) {
            e.preventDefault();
            var text = e.clipboardData.getData('text/plain').replace(/\n/ig, '<br>');
            document.execCommand('insertHTML', false, text);
        });

    };

    EasyEditor.prototype.isSelectionInsideElement = function(tagName) {
        var sel, containerNode;
        tagName = tagName.toUpperCase();
        if (window.getSelection) {
            sel = window.getSelection();
            if (sel.rangeCount > 0) {
                containerNode = sel.getRangeAt(0).commonAncestorContainer;
            }
        } else if ( (sel = document.selection) && sel.type != "Control" ) {
            containerNode = sel.createRange().parentElement();
        }
        while (containerNode) {
            if (containerNode.nodeType == 1 && containerNode.tagName == tagName) {
                return true;
            }
            containerNode = containerNode.parentNode;
        }
        return false;
    };

    // adding toolbar
    EasyEditor.prototype.addToolbar = function(){
        var _this = this;

        $(_this.elem).before('<div class="'+ _this.className +'-toolbar"><ul></ul></div>');
        this.$toolbarContainer = this.$wrapperElem.find('.' + _this.className +'-toolbar');

        this.populateButtons();
    };

    // inejct button events
    EasyEditor.prototype.injectButton = function(settings){
        var _this = this;

        // overwritting default button settings
        if(_this.overwriteButtonSettings !== null && _this.overwriteButtonSettings[settings.buttonIdentifier] !== undefined) {
            var newSettings = $.extend({}, settings, _this.overwriteButtonSettings[settings.buttonIdentifier]);
            settings = newSettings;
        }

        // if button html exists overwrite default button html
        if(_this.buttonsHtml !== null && _this.buttonsHtml[settings.buttonIdentifier] !== undefined) {
            settings.buttonHtml = _this.buttonsHtml[settings.buttonIdentifier];
        }

        // if buttonTitle parameter exists
        var buttonTitle;
        if(settings.buttonTitle) {
            buttonTitle = settings.buttonTitle;
        }
        else {
            buttonTitle = settings.buttonIdentifier.replace(/\W/g, ' ');
        }

        // adding button html
        if(settings.buttonHtml) {
            if(settings.childOf !== undefined) {
                var $parentContainer = _this.$toolbarContainer.find('.toolbar-' + settings.childOf).parent('li');

                if($parentContainer.find('ul').length === 0) {
                    $parentContainer.append('<ul></ul>');
                }

                $parentContainer = $parentContainer.find('ul');
                $parentContainer.append('<li><button class="toolbar-'+ settings.buttonIdentifier +'" title="'+ buttonTitle +'">'+ settings.buttonHtml +'</button></li>');
            }
            else {
                _this.$toolbarContainer.children('ul').append('<li><button class="toolbar-'+ settings.buttonIdentifier +'" title="'+ buttonTitle +'">'+ settings.buttonHtml +'</button></li>');
            }
        }

        // bind click event
        if(typeof settings.clickHandler === 'function') {
            $('html').find(_this.elem).closest(_this.containerClass).delegate('.toolbar-'+ settings.buttonIdentifier, 'click', function(event){
                if(typeof settings.hasChild !== undefined && settings.hasChild === true) {
                    event.stopPropagation();
                }
                else {
                    event.preventDefault();
                }

                settings.clickHandler.call(this);
                $(_this.elem).trigger('keyup');
            });
        }
    };

    // open dropdown
    EasyEditor.prototype.openDropdownOf = function(identifier){
        var _this = this;
        $(_this.elem).closest(_this.containerClass).find('.toolbar-' + identifier).parent().children('ul').show();
    };

    // bidning all buttons
    EasyEditor.prototype.populateButtons = function(){
        var _this = this;

        $.each(_this.buttons, function(index, button) {
            if(typeof _this[button] === 'function'){
                _this[button]();
            }
        });

    };

    // allowing resizing image
    EasyEditor.prototype.handleResizeImage = function(){
        var _this = this;

        $('html').delegate(_this.containerClass + ' figure', 'click', function(event) {
            event.stopPropagation();
            $(this).addClass('is-resizable');
        });

        $('html').delegate(_this.containerClass + ' figure.is-resizable', 'mousemove', function(event) {
            $(this).find('img').css({ 'width' : $(this).width() + 'px' });
        });

        $(document).click(function() {
            $(_this.elem).find('figure').removeClass('is-resizable');
        });
    };

    // get selection
    EasyEditor.prototype.getSelection = function(){
        if (window.getSelection) {
            var selection = window.getSelection();

            if (selection.rangeCount) {
                return selection;
            }
        }

        return false;
    };
    EasyEditor.prototype.getCurrentPos = function(){
        if(!this.isSelectionOutsideOfEditor()){
             var caretPos,sel, range;
            if (window.getSelection) {
                sel = window.getSelection();
                if (sel.rangeCount) {
                    range = sel.getRangeAt(0);
                    if (range.commonAncestorContainer.parentNode == this.elem) {
                        caretPos = range.endOffset;
                    }
                }
            } else if (document.selection && document.selection.createRange) {
                range = document.selection.createRange();
                if (range.parentElement() == editableDiv) {
                    var tempEl = document.createElement("span");
                    editableDiv.insertBefore(tempEl, editableDiv.firstChild);
                    var tempRange = range.duplicate();
                    tempRange.moveToElementText(tempEl);
                    tempRange.setEndPoint("EndToEnd", range);
                    caretPos = tempRange.text.length;
                }
            }
            return caretPos;
        }else{
            //没有选择的话默认在第一个字
            return 0;
        }
    }
    // remove formatting
    EasyEditor.prototype.removeFormatting = function(arg){
        var _this = this;
        var inFullArea = arg.inFullArea;

        if(_this.isSelectionOutsideOfEditor() === true) {
            return false;
        }

        if(inFullArea === false) {
            var selection = _this.getSelection();
            var selectedText = selection.toString();

            if(selection && selectedText.length > 0) {

                var range = selection.getRangeAt(0);
                var $parent = $(range.commonAncestorContainer.parentNode);

                if($parent.attr('class') === _this.className || $parent.attr('class') === _this.className + '-wrapper') {
                    var node = document.createElement('span');
                    $(node).attr('data-value', 'temp').html(selectedText.replace(/\n/ig, '<br>'));
                    range.deleteContents();
                    range.insertNode(node);

                    $('[data-value="temp"]').contents().unwrap();
                }
                else {

                    var topMostParent;
                    var hasParentNode = false;
                    $.each($parent.parentsUntil(_this.elem), function(index, el) {
                        topMostParent = el;
                        hasParentNode = true;
                    });

                    if(hasParentNode === true) {
                        $(topMostParent).html($(topMostParent).text().replace(/\n/ig, '<br>')).contents().unwrap();
                    }
                    else {
                        $parent.contents().unwrap();
                    }

                }

            }
        }
        else {
            $(_this.elem).html($(_this.elem).text().replace(/\n/ig, '<br>'));
        }

        // _this.removeEmptyTags();
    };

    // removing empty tags
    EasyEditor.prototype.removeEmptyTags = function(){
        var _this = this;
        $(_this.elem).html( $(_this.elem).html().replace(/(<(?!\/)[^>]+>)+(<\/[^>]+>)+/, '') );
    };

    // remove block elemenet from selection
    EasyEditor.prototype.removeBlockElementFromSelection = function(selection, removeBr){
        var _this = this;
        var result;

        removeBr = removeBr === undefined ? false : removeBr;
        var removeBrNode = '';
        if(removeBr === true) {
            removeBrNode = ', br';
        }

        var range = selection.getRangeAt(0);
        var selectedHtml = range.cloneContents();
        var temp = document.createElement('temp');
        $(temp).html(selectedHtml);
        $(temp).find('h1, h2, h3, h4, h5, h6, p, div' + removeBrNode).each(function() { $(this).replaceWith(this.childNodes); });
        result = $(temp).html();

        return result;
    };

    // wrap selction with a tag
    EasyEditor.prototype.wrapSelectionWithNodeName = function(arg){
        var _this = this;
        if(_this.isSelectionOutsideOfEditor() === true) {
            return false;
        }

        var node = {
            name: 'span',
            blockElement: false,
            style: null,
            class: null,
            attribute: null,
            keepHtml: false
        };

        if(typeof arg === 'string') {
            node.name = arg;
        }
        else {
            node.name = arg.nodeName || node.name;
            node.blockElement = arg.blockElement || node.blockElement;
            node.style = arg.style || node.style;
            node.class = arg.class || node.class;
            node.attribute = arg.attribute || node.attribute;
            node.keepHtml = arg.keepHtml || node.keepHtml;
        }

        var selection = _this.getSelection();

        if(arg.insertFunc || (selection && selection.toString().length > 0 && selection.rangeCount)) {
            // checking if already wrapped
            var isWrapped = _this.isAlreadyWrapped(selection, node);

            // wrap node
            var range = selection.getRangeAt(0).cloneRange();
            var tag = document.createElement(node.name);

                // adding necessary attribute to tag
                if(node.style !== null || node.class !== null || node.attribute !== null) {
                    if(selection && selection.toString().length > 0 && selection.rangeCount){
                        tag = _this.addAttribute(tag, node);
                    }else{
                        tag = arg.insertFunc(tag, node);
                    }
                }

            // if selection contains html, surround contents has some problem with pre html tag and raw text selection
            if(_this.selectionContainsHtml(range)) {
                range = selection.getRangeAt(0);

                if(node.keepHtml === true) {
                    var clonedSelection = range.cloneContents();
                    var div = document.createElement('div');
                    div.appendChild(clonedSelection);
                    $(tag).html(div.innerHTML);
                }
                else if(selection.toString().length > 0 && selection.rangeCount){
                    tag.textContent = selection.toString();
                }

                range.deleteContents();
                range.insertNode(tag);

                if(range.commonAncestorContainer.localName === node.name) {
                    $(range.commonAncestorContainer).contents().unwrap();
                    _this.removeEmptyTags();
                }
            }
            else {
                range.surroundContents(tag);
                selection.removeAllRanges();
                selection.addRange(range);
            }

            if(isWrapped === true) {
                _this.removeWrappedDuplicateTag(tag);
            }

            _this.removeEmptyTags();
            selection.removeAllRanges();
        }
    };

    // wrap selection with unordered list
    EasyEditor.prototype.wrapSelectionWithList = function(tagname){
        var _this = this;
        tagname = tagname || 'ul';

        // preventing outside selection
        if(_this.isSelectionOutsideOfEditor() === true) {
            return false;
        }

        // if text selected
        var selection = _this.getSelection();
        if(selection && selection.toString().length > 0 && selection.rangeCount) {
            var selectedHtml = _this.removeBlockElementFromSelection(selection, true);
            var listArray = selectedHtml.split('\n').filter(function(v){return v!=='';});
            var wrappedListHtml = $.map(listArray, function(item) {
                return '<li>' + $.trim(item) + '</li>';
            });

            var node = document.createElement(tagname);
            $(node).html(wrappedListHtml);

            var range = selection.getRangeAt(0);
            range.deleteContents();
            range.insertNode(node);

            selection.removeAllRanges();
        }

    };

    // if selection contains html tag, surround content fails if selection contains html
    EasyEditor.prototype.selectionContainsHtml = function(range){
        var _this = this;
        if(range.startContainer.parentNode.className === _this.className + '-wrapper') return false;
        else return true;
    };

    // if already wrapped with same tag
    EasyEditor.prototype.isAlreadyWrapped = function(selection, node){
        var _this = this;
        var range = selection.getRangeAt(0);
        var el = $(range.commonAncestorContainer);
        var result = false;

        if( el.parent().prop('tagName').toLowerCase() === node.name && el.parent().hasClass(_this.className) === false ) {
            result = true;
        }
        else if(node.blockElement === true) {
            $.each(el.parentsUntil(_this.elem), function(index, el) {
                var tag = el.tagName.toLowerCase();
                if( $.inArray(tag, ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']) !== -1 ) {
                    result = true;
                }
            });
        }
        else {
            $.each(el.parentsUntil(_this.elem), function(index, el) {
                var tag = el.tagName.toLowerCase();
                if( tag === node.name ) {
                    result = true;
                }
            });
        }

        return result;
    };

    // remove wrap if already wrapped with same tag
    EasyEditor.prototype.removeWrappedDuplicateTag = function(tag){
        var _this = this;
        var tagName = tag.tagName;

        $(tag).unwrap();

        if($(tag).prop('tagName') === tagName && $(tag).parent().hasClass(_this.className) === false && $(tag).parent().hasClass(_this.className + '-wrapper')) {
            $(tag).unwrap();
        }
    };

    // adding attribute in tag
    EasyEditor.prototype.addAttribute = function(tag, node){
        if(node.style !== null) {
            $(tag).attr('style', node.style);
        }

        if(node.class !== null) {
            $(tag).addClass(node.class);
        }

        if(node.attribute !== null) {
            if($.isArray(node.attribute) === true) {
                $(tag).attr(node.attribute[0], node.attribute[1]);
            }
            else {
                $(tag).attr(node.attribute);
            }
        }

        return tag;
    };

    // insert a node into cursor point in editor
    EasyEditor.prototype.insertAtCaret = function(node,setRange){
        var _this = this;
        if(_this.isSelectionOutsideOfEditor() === true && typeof setRange === "undefined") {
                return false;
        }
        if(setRange){
            range = setRange;
            range.insertNode(node);
            var sel = window.getSelection();
            range.collapse(true);
            sel.removeAllRanges();
            sel.addRange(range);

        }else if(_this.getSelection()) {
            var range = _this.getSelection().getRangeAt(0);
            range.insertNode(node);
        }
        else {
            $(node).appendTo(_this.elem);
        }
    };

    // checking if selection outside of editor or not
    EasyEditor.prototype.isSelectionOutsideOfEditor = function(){
        return !this.elementContainsSelection(this.elem);
    };

    // node contains in containers or not
    EasyEditor.prototype.isOrContains = function(node, container) {
        while (node) {
            if (node === container) {
                return true;
            }
            node = node.parentNode;
        }
        return false;
    };

    // selected text is inside container
    EasyEditor.prototype.elementContainsSelection = function(el) {
        var _this = this;
        var sel;
        if (window.getSelection) {
            sel = window.getSelection();
            if (sel.rangeCount > 0) {
                for (var i = 0; i < sel.rangeCount; ++i) {
                    if (!_this.isOrContains(sel.getRangeAt(i).commonAncestorContainer, el)) {
                        return false;
                    }
                }
                return true;
            }
        } else if ( (sel = document.selection) && sel.type !== "Control") {
            return _this.isOrContains(sel.createRange().parentElement(), el);
        }
        return false;
    };

    // insert html chunk into editor's temp tag
    EasyEditor.prototype.insertHtml = function(html){
        var _this = this;
        $(_this.elem).find('temp').html(html);
    };

    // utility of editor
    EasyEditor.prototype.utils = function(){
        var _this = this;

        $('html').delegate('.'+ _this.className +'-modal-close', 'click', function(event) {
            event.preventDefault();
            _this.closeModal('#' + $(this).closest('.'+ _this.className + '-modal').attr('id'));
        });

        if( $('.' + _this.randomString + '-bind').length > 0 ) {
            var bindData;
            $('html').delegate(_this.elem, 'click keyup', function() {
                var el = _this.elem;
                clearTimeout(bindData);
                bindData = setTimeout(function(){ $('.' + _this.randomString + '-bind').html( $(el).html() ); }, 250);
            });
        }

        $(document).click(function(event) {
            $('.' + _this.className).closest('.' + _this.className + '-wrapper').find('.' + _this.className + '-toolbar > ul > li > ul').hide();
        });
    };

    // youtube video id from url
    EasyEditor.prototype.getYoutubeVideoIdFromUrl = function(url){
        if(url.length === 0) return false;
        var videoId = '';
        url = url.replace(/(>|<)/gi,'').split(/(vi\/|v=|\/v\/|youtu\.be\/|\/embed\/)/);
        if(url[2] !== undefined) {
            videoId = url[2].split(/[^0-9a-z_\-]/i);
            videoId = videoId[0];
        }
        else {
            videoId = url;
        }
        return videoId;
    };

    // opening modal window
    EasyEditor.prototype.openModal = function(selector){
        var temp = document.createElement('temp');
        temp.textContent = '.';
        this.insertAtCaret(temp);

        $(selector).removeClass('is-hidden');
    };

    // closing modal window
    EasyEditor.prototype.closeModal = function(selector){
        var _this = this;

        $(selector).addClass('is-hidden').find('input').val('');
        $(selector).find('.' + _this.className + '-modal-content-body-loader').css('width', '0');
        var $temp = $(this.elem).find('temp');

        if($temp.html() === '.') {
            $temp.remove();
        }
        else {
            $temp.contents().unwrap();
        }

        $(this.elem).focus();
    };

    EasyEditor.prototype.bold = function(){
        var _this = this;
        var settings = {
            buttonIdentifier: 'bold',
            buttonHtml: 'B',
            clickHandler: function(){
                _this.wrapSelectionWithNodeName({ nodeName: 'strong', keepHtml: true });
            }
        };

        _this.injectButton(settings);
    };

    EasyEditor.prototype.italic = function(){
        var _this = this;
        var settings = {
            buttonIdentifier: 'italic',
            buttonHtml: 'I',
            clickHandler: function(){
                _this.wrapSelectionWithNodeName({ nodeName: 'em', keepHtml: true });
            }
        };

        _this.injectButton(settings);
    };

    EasyEditor.prototype.h2 = function(){
        var _this = this;
        var settings = {
            buttonIdentifier: 'header-2',
            buttonHtml: 'H2',
            clickHandler: function(){
                _this.wrapSelectionWithNodeName({ nodeName: 'h2', blockElement: true });
            }
        };

        _this.injectButton(settings);
    };

    EasyEditor.prototype.h3 = function(){
        var _this = this;
        var settings = {
            buttonIdentifier: 'header-3',
            buttonHtml: 'H3',
            clickHandler: function(){
                _this.wrapSelectionWithNodeName({ nodeName: 'h3', blockElement: true });
            }
        };

        _this.injectButton(settings);
    };

    EasyEditor.prototype.h4 = function(){
        var _this = this;
        var settings = {
            buttonIdentifier: 'header-4',
            buttonHtml: 'H4',
            clickHandler: function(){
                _this.wrapSelectionWithNodeName({ nodeName: 'h4', blockElement: true });
            }
        };

        _this.injectButton(settings);
    };

    EasyEditor.prototype.x = function(){
        var _this = this;
        var settings = {
            buttonIdentifier: 'remove-formatting',
            buttonHtml: 'x',
            clickHandler: function(){
                _this.removeFormatting({ inFullArea: false });
            }
        };

        _this.injectButton(settings);
    };

    EasyEditor.prototype.alignleft = function(){
        var _this = this;
        var settings = {
            buttonIdentifier: 'align-left',
            buttonHtml: 'Align left',
            clickHandler: function(){
                _this.wrapSelectionWithNodeName({ nodeName: 'p', style: 'text-align: left', class: 'text-left', keepHtml: true });
            }
        };

        _this.injectButton(settings);
    };

    EasyEditor.prototype.aligncenter = function(){
        var _this = this;
        var settings = {
            buttonIdentifier: 'align-center',
            buttonHtml: 'Align center',
            clickHandler: function(){
                _this.wrapSelectionWithNodeName({ nodeName: 'p', style: 'text-align: center', class: 'text-center', keepHtml: true });
            }
        };

        _this.injectButton(settings);
    };

    EasyEditor.prototype.alignright = function(){
        var _this = this;
        var settings = {
            buttonIdentifier: 'align-right',
            buttonHtml: 'Align right',
            clickHandler: function(){
                _this.wrapSelectionWithNodeName({ nodeName: 'p', style: 'text-align: right', class: 'text-right', keepHtml: true });
            }
        };

        _this.injectButton(settings);
    };

    EasyEditor.prototype.quote = function(){
        var _this = this;
        var settings = {
            buttonIdentifier: 'quote',
            buttonHtml: 'Quote',
            clickHandler: function(){
                _this.wrapSelectionWithNodeName({ nodeName: 'blockquote' });
            }
        };

        _this.injectButton(settings);
    };

    EasyEditor.prototype.code = function(){
        var _this = this;
        var settings = {
            buttonIdentifier: 'code',
            buttonHtml: 'Code',
            clickHandler: function(){
                _this.wrapSelectionWithNodeName({ nodeName: 'pre' });
            }
        };

        _this.injectButton(settings);
    };

    EasyEditor.prototype.link = function(){
        var _this = this;
        var settings = {
            buttonIdentifier: 'link',
            buttonHtml: 'Link',
            clickHandler: function(){
                function makeDefaultLink(tag,node){
                    if(node.style !== null) {
                        $(tag).attr('style', node.style);
                    }

                    if(node.class !== null) {
                        $(tag).addClass(node.class);
                    }

                    if(node.attribute !== null) {
                        if($.isArray(node.attribute) === true) {
                            $(tag).attr(node.attribute[0], node.attribute[1]);
                        }
                        else {
                            $(tag).attr(node.attribute);
                        }
                    }
                    $(tag).html(node.attribute[1]);
                    return tag;
                };
                _this.wrapSelectionWithNodeName({ nodeName: 'a', attribute: ['href', prompt('Insert link', '')],insertFunc:makeDefaultLink});
            }
        };

        _this.injectButton(settings);
    };

    EasyEditor.prototype.list = function(){
        var _this = this;
        var settings = {
            buttonIdentifier: 'list',
            buttonHtml: 'List',
            clickHandler: function(){
                _this.wrapSelectionWithList();
            }
        };

        _this.injectButton(settings);
    };

    var IMG_HTML = '<div class="row easyeditor-modal-content-body"><div class="row"><div class="col-xs-12 col-sm-8 col-lg-8 col-md-8" style="padding:0px 15px 0px 15px">' +
        '<div class="easyeditor-modal-content-image easyeditor-modal-content-loading" id="@id"></div></div>' +
        '<div class="col-xs-12 col-sm-4 col-lg-4 col-md-4">' +
        '<div class="row" id="@fileInfoId"></div><div class="row easyeditor-modal-controlPanel" id="@controlPanel"></div></div>' +
        '</div></div>';

    var FILE_INFO_HTML = '<div class="col-xs-12 col-sm-12 col-lg-12 col-md-12" style="overflow: hidden" title="@fileName">@fileName</div>' +
        '<div class="col-xs-12 col-sm-12 col-lg-12 col-md-12">@fileSize</div>'
        + '<div class="col-xs-12 col-sm-12 col-lg-12 col-md-12" data-id="fileRatio">@fileRatio</div>'

    var CONTROL_SILIDER_BAR_HTML = '<div class="col-xs-12 col-sm-12 col-lg-12 col-md-12">图片缩放比例：<span class="easyeditor-imgScroll-value">100%</span></div>' +
        '<div class="col-xs-12 col-sm-12 col-lg-12 col-md-12"><input type="range" class="easyeditor-controlSlider"/></div>';

    var ERROR_INFO = '<div class="col-xs-12 col-sm-12 col-lg-12 col-md-12" style="color:#ff0000">@errorInfo</div>';

    var EasyEditor_DEF_imgaeOpt = {
        fileLabel:"文件名：",
        sizeLabel:"文件大小：",
        ratioLabel:"分辨率：",
    };
    EasyEditor.prototype.image = function(){
        var _this = this;
        _this.loadFIles = _this.loadFIles||[];
        var settings = {
            buttonIdentifier: 'insert-image',
            buttonHtml: 'Insert image',
        };
        require(["/Content/js/teld-lib/teld-com/teld-Modal.js"],function(MODEL_MA){
            var htmlText = IMG_HTML;
            htmlText = IMG_HTML.replace("@id", "img_sele" + _this.randomString);
            htmlText = htmlText.replace("@fileInfoId", "fileInfo" + _this.randomString);
            htmlText = htmlText.replace("@controlPanel", "controlPanel" + _this.randomString);

            settings.clickHandler = function(){
                MODEL_MA.show({title:"选择图片",html:htmlText,dialogCls:"easyeditor-modal-dialog"});
                _this.loadTmpFile = null;
                _this.imgSelect = $("#img_sele" + _this.randomString);
                _this.fileInfo = $("#fileInfo" + _this.randomString);
                var currentRange = null;
                if(_this.getSelection()){
                    currentRange =  _this.getSelection().getRangeAt(0);
                }

                var controlPanel = $("#controlPanel" + _this.randomString);
                    _this.uploadManager = $(new TeldUpdateManager({imgSel:_this.imgSelect,acceptType:"image/*"}));

                _this.uploadManager.on("uploadManagerFileChange",function(){
                    _this.imgSelect.html("");
                    _this.fileInfo.html("");
                    controlPanel.html("");
                });

               _this.uploadManager.on("uploadManagerFileError",function(e, error){
                   _this.fileInfo = $("#fileInfo" + _this.randomString);
                   _this.imgSelect.addClass("easyeditor-modal-content-loading");
                   var errorTxt = ERROR_INFO.replace("@errorInfo", error.err);
                    _this.fileInfo.html("");
                    _this.fileInfo.html(errorTxt);
                });


                    _this.uploadManager.on("uploadManagerFileLoadBase64End",
                        function (e, args){
                            var file  = args.file;
                            var content = args.data;
                            _this.imgSelect.html("");
                            _this.fileInfo.html("");
                            controlPanel.html("");
                            _this.imgSelect.removeClass("easyeditor-modal-content-loading");
                            var sizeObj = calculateImageSize(_this.imgSelect, {width:file.naturalWidth, height:file.naturalHeight});
                            var style = "";
                            if(typeof sizeObj.maxWidth !== "undefined"){
                                style = style + "max-width:" + sizeObj.maxWidth + "px";
                            }
                            if(typeof sizeObj.maxHeight !== "undefined"){
                                style = style + "max-height:" + sizeObj.maxHeight + "px";
                            }
                            var imgageHtml = '<img src="' + content + '" alt="' + file.name +'" + style="' + style +'"/>'
                            _this.imgSelect.append(imgageHtml);

                            var info = FILE_INFO_HTML;

                            info = info.replace(/@fileName/g, EasyEditor_DEF_imgaeOpt.fileLabel + file.name);
                            info = info.replace(/@fileSize/g, EasyEditor_DEF_imgaeOpt.sizeLabel + caculateSize(file.size));
                            info = info.replace(/@fileRatio/g, EasyEditor_DEF_imgaeOpt.ratioLabel + file.naturalWidth + "*" + file.naturalHeight );

                            _this.fileInfo.append(info);
                            controlPanel.append(CONTROL_SILIDER_BAR_HTML);

                            var controlSlider = controlPanel.find(".easyeditor-controlSlider");
                            controlSlider.val(100);
                            controlSlider.change(
                                function(){
                                    var max = controlSlider.attr("max");
                                    if(typeof max === "undefined"){
                                        max = 1;
                                    }
                                    var rate = controlSlider.val()/max;
                                    controlPanel.find(".easyeditor-imgScroll-value").html(rate + "%")
                                }
                            );
                            file.rate = 1;
                            var refreshValue =    function(){
                                var max = controlSlider.attr("max");
                                if(typeof max === "undefined"){
                                    max = 1;
                                }
                                var rate = controlSlider.val()/max;
                                controlPanel.find(".easyeditor-imgScroll-value").html(rate + "%");
                                file.rate = rate/100;
                                _this.fileInfo.find("[data-id='fileRatio']").html("");
                                _this.fileInfo.find("[data-id='fileRatio']").html(EasyEditor_DEF_imgaeOpt.ratioLabel + parseInt(file.naturalWidth * file.rate) + "*" + parseInt(file.rate * file.naturalHeight));
                            };

                            controlSlider.change(
                                refreshValue
                            );

                            controlSlider.on("input",refreshValue);
                            _this.loadTmpFile = {file:file, base64:content,id:getIncrementId()};
                        }

                    );

                MODEL_MA.dialog.on(MODEL_MA.ENTER_CLICK_EVENT, function(){
                    MODEL_MA.dialog.off(MODEL_MA.ENTER_CLICK_EVENT);
                    if(_this.loadTmpFile){
                        var file = _this.loadTmpFile.file;
                        var img = new Image();
                        var jimg = $(img);
                        img.alt = file.name;
                        var width = file.naturalWidth * file.rate;
                        var height = file.naturalHeight * file.rate;
                        jimg.css("max-width", parseInt(width) + "px");
                        jimg.css("max-height", parseInt(height) + "px");
                        jimg.attr("data-incrementId", _this.loadTmpFile.id);
                        jimg.attr("data-width", width);
                        jimg.attr("data-height", height);

                        var limitWidth = $(_this.elem).innerWidth() * 0.9;
                        var limtiHeight = "auto";
                       var sizeObj = calculateImageSize({width:limitWidth,height:limtiHeight}, {width:width,height:height});
                        if(sizeObj.maxWidth && sizeObj.maxWidth != width){
                            jimg.css("max-width", parseInt(sizeObj.maxWidth) + "px");
                        }
                        img.src = _this.loadTmpFile.base64;
                        _this.loadTmpFile.elem = jimg;
                        _this.loadFIles.push(_this.loadTmpFile);
                        _this.insertAtCaret(img,currentRange);
                    }
                });
            };
            _this.injectButton(settings);
        })
    };
    function caculateSize(size) {
        if (size < 100) {
            return size + "byte";
        }

        if (size < 1024 * 1024) {
            return (size / 1024).toFixed(2) + "K";
        }
        if (size < 1024 * 1024 * 1024) {
            return (size / 1024 / 1024).toFixed(2) + "M";
        }
        if (size < 1024 * 1024 * 1024 * 1024) {
            return (size / 1024 / 1024 / 1024).toFixed(2) + "G";
        }
        if (size < 1024 * 1024 * 1024 * 1024 * 1024) {
            console.info("你牛逼，1TB的文件，你传的啥？")
            return (size / 1024 / 1024 / 1024 / 1024).toFixed(2) + "TB";
        }
        console.info("1PB的文件？现在是2500年？")
        return (size / 1024 / 1024 / 1024 / 1024/1024).toFixed(2) + "PB";

    }

    function calculateImageSize(jcontainer, contentSize){
        var w = contentSize.width;
        var h = contentSize.height;
        var maxW = 1;
        var maxH = 1;

        if(typeof jcontainer.width === "function"){
            maxW = jcontainer.width();
        }else{
            maxW = jcontainer.width;
        }
        if(typeof jcontainer.height === "function"){
            maxH = jcontainer.height();
        }else{
            maxH = jcontainer.height;
        }

        if(maxW === "auto"){
            maxW = w;
        }

        if(maxH === "auto"){
            maxH = h;
        }

        if(w <= maxW && h <= maxH){
            return {};
        }
        if(w >= maxW && h <= maxH){
            return {maxWidth:maxW};
        }

        if(w <= maxW && h >= maxH){
            return {maxHeight:maxH};
        }

        if(w/maxW > h/maxH){
            return {maxWidth:maxW};
        }else{
            return {maxHeight:maxH};
        }

    }

    var TeldUpdateManager_OPT = {
        max_size:1048576,
        acceptType:"*",
    }

    var INCREMENT_ID = 0;

    function getIncrementId(){
        return ++INCREMENT_ID;
    }

    var TeldUpdateManager = function(options){
        var inputFile = $(".easyeditor-innputFile");
        if(inputFile.length == 0){
             inputFile = $('<input type="file" accept="image/*"  class="easyeditor-innputFile" style="display: none;position: absolute; top: 0px; left: 0px; height: 0px; width: 0px;"/>');
             $(document.body).append(inputFile);
        }
        var that = this;
        this.options = $.extend({},TeldUpdateManager_OPT,options);

        options.imgSel.click(
            function(){
                inputFile.click();
            }
        );
        var hangdleError = function(error){
            $(that).trigger("uploadManagerFileError",error);
        }
        inputFile.change(
            function(){
                $(that).trigger("uploadManagerFileChange",{file:this.file});
                if(this.files.length > 0){
                    var error = that.checkFile(this.files[0]);
                    if(error != null){
                        hangdleError(error);
                        return;
                    }
                }
                $(that).trigger("uploadManagerFileLoadEnd",this.files[0]);
                var reader = new FileReader();
                reader.readAsDataURL(this.files[0]);
                var file = this.files[0];
                reader.onload = function(){
                    if(file.isImage){
                        var img = new Image();
                        img.src = reader.result;
                        img.onload = function(){
                            file.naturalWidth = img.naturalWidth;
                            file.naturalHeight = img.naturalHeight;
                            $(that).trigger("uploadManagerFileLoadBase64End",{file:file, data:reader.result});
                        }
                    }
                    else{
                        $(that).trigger("uploadManagerFileLoadBase64End",{file:file, data:reader.result});
                    }
                }
            }
        );
    }
    TeldUpdateManager.prototype.ERR_FILE_SIZE = 1;

    TeldUpdateManager.prototype.ERR_FILE_TYPE = 2;

    TeldUpdateManager.prototype.checkFile = function(file){
        var error = null;
        if(file.size > this.options.max_size){
            error = error || {};
            error.code =  this.ERR_FILE_SIZE;
            error.err = "超过最大限制，最大文件是：" + caculateSize(this.options.max_size);
            return error;
        }
       if(this.options.acceptType != "*"){
           var mimeType = file.type;
           var baseMimeType = mimeType.replace(/\/.*$/, "");
           var validType = this.options.acceptType;
           validType = validType.trim();
           if(baseMimeType == "image"){
               file.isImage = true;
           }
           var find = false;
           if (validType.charAt(0) === ".") {
               if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) {
                   find = true;
               }
           } else if (/\/\*$/.test(validType)) {
               if (baseMimeType === validType.replace(/\/.*$/, "")) {
                   find = true;
               }
           } else {
               if (mimeType === validType) {
                   find = true;
               }
           }
           if(!find){
               error = error || {};
               error.code = this.ERR_FILE_TYPE;
               error.err= "文件类型错误";
               return error;
           }
       }

        return null;
    }

    EasyEditor.prototype.sendObject = function(sessionId){
        var that = this;
        require(["/Content/js/teld-lib/teld-file/teld-fileIO.js"], function(fileIO){
            if(that.loadFIles && that.loadFIles.length > 0) {
                var sendOption = {sessionId: sessionId, files: [],updSuccess:that.updImgSuccess,ctx:that};
                for (var i = 0; i < that.loadFIles.length; i++) {
                    var tmp = that.loadFIles[i];
                    var names = tmp.file.name.split(".");
                    var w = tmp.elem.data("width");
                    var h = tmp.elem.data("height");
                    tmp.file.def = tmp;
                    var file = {
                        data: tmp.base64,
                        name: tmp.file.name,
                        ext: names[names.length - 1],
                        Parameters: {width: w, height: h, watermark: that.imageSetting.watermark},
                        file: tmp.file,
                        elem:tmp.elem,
                    };
                    sendOption.files.push(file);
                }
                fileIO.uploadMulImg(sendOption);
            }else{
                $(this).trigger(EVENT_SEND_SUCCESS);
                this.contentText = $(this.elem).html();
            }
        });
    }
    EasyEditor.prototype.updImgSuccess = function(retData,content){
        var backContent = $("<div style='display:none'></div>")
        $(document.body).append(backContent);
        backContent.html($(this.elem).html());
        for(var i = 0; i < content.length; i++){
            var con = content[i];
            con.elem.attr("data-src", retData.RelativeUrls[i]);
            var img = backContent.find("[data-incrementId='"+  con.elem.attr("data-incrementId") + "']");
            img.attr("src","");
            img.attr("data-src", retData.RelativeUrls[i]);
        }
        var text = backContent.html();
        $(this).trigger(EVENT_SEND_SUCCESS);
        backContent.remove();
        this.contentText = text;
    }

    EasyEditor.prototype.pareseText = function(text,sessionId, append){
        var backContent = $("<div style='display:none'></div>")
        backContent.html(text);
        this.backContent = backContent;
        var imgs = backContent.find("[data-incrementId]");

        if(!append){
            this.loadFIles = [];
            $(this.elem).html("");
        }
        this.loadingFIles = [];
        var options = {sessionId:sessionId, url_pre_fix:"",req:[],ctx:this, downloadSuccess:this.downloadSuccess};

        for(var i = 0; i < imgs.length; i++){
            var con = $(imgs[i]);
            var id = getIncrementId();
            imgs[i].attr("[data-incrementId]", id);
            var file = {id:id,watermark:this.imageSetting.watermark,relativeurl:con.attr("data-src"),img:con};
            options.req.push(file);
            this.loadingFIles.push(file);
        }
        if(imgs.length > 0){
            require(["/Content/js/teld-lib/teld-file/teld-fileIO.js"], function(fileIO) {
                fileIO.downloadImgFile(options);
            });
        }else{
            $(this.elem).append(this.backContent.html());
            this.backContent.remove();
            this.backContent = null;
        }


    }
    EasyEditor.prototype.downloadSuccess = function(retData,req){
        var nm = req.img.attr("alt");
        var nms = nm.split(".");
        var header = "data:image/" + nms[nms.length-1] + ";base64,";
        req.img.attr("src",header + retData.Data);

        for(var i = 0; i < this.loadingFIles.length; i++){
            if(this.loadingFIles.id == req.id){
                this.loadingFIles.splice(i,1);
                break;
            }
        }
        this.loadFIles.push(req);
        if(this.loadingFIles.length == 0){
            $(this.elem).append(this.backContent.html());
            this.backContent.remove();
            this.backContent = null;
        }
    }

    window.EasyEditor = EasyEditor;

    $.fn.easyEditor = function ( options ) {
        return this.each(function () {
            if (!$.data(this, 'plugin_easyEditor')) {
                $.data(this, 'plugin_easyEditor',
                new EasyEditor( this, options ));
            }
        });
    };

})(jQuery, document, window);
