
(function($) {

  // the type variable below must be set to the underscored version of the field type key
  // e.g. if you have a field type with key 'my-editor', the type variable below would be "my_editor"
  
  
  var field_type = "visual_editor";
  
  // validity checks - do not remove
  if ($.fn["mpft_" + field_type]) { throw(sprintf($.mp.errors.duplicate_widget, field_type)); } else if (field_type == "type_key") { throw(sprintf($.mp.errors.incomplete_widget, field_type)); }

  
  $.widget( "ui.mpft_" + field_type, $.ui.mpft, {

  	options: {
      
  	},

    focus: function() {
      var self = this;
      
      if (self.ui.button_visual.length) {
        
        if (self.ui.button_visual.hasClass("current")) {
          tinyMCE.execCommand('mceFocus', false, this.mceId);
        } else {
          if (this.using_cm()) {
            self.codeMirror.focus();
          } else {
            self.ui.textarea.focus();
          }
        }

      }
      
      self.focus_field();
    },
    
    cache_ui: function() {
      this.ui = this.ui || {
        button_visual: this.element.find(".tab-button.visual"),
        button_html: this.element.find(".tab-button.html"),
        textarea: this.element.find("textarea")
      };      
    },
    
    ontoggleexpand: function() {
      var self = this;
      if (self.ui.button_visual.hasClass("current")) {
        self.mce_add();
      }
    },
    
    is_readonly: function() {
      return (this.ui.textarea.attr("readonly") == "readonly"); 
    },
    
  	onfirstexpand: function() {
      
      var self = this;
      
      if (window.tinymce || window.tinyMCE) {
        
        this.mce4 = window.tinymce && parseInt(window.tinymce.majorVersion, 10) >= 4;
      
        this.cache_ui();
      
        var mceInit = {};
      
        if (tinyMCEPreInit) {
          mceInit = tinyMCEPreInit.mceInit || {};
        }
      
        if (this.element.closest('#addtag').length) {
          // we're editing within the AJAX-based tag add screen
        
          self.saveOnChange = true;        
        }
      
        // Wordpress 3.3 patch (this will need some more thought when I can more fully understand the API changes)
      
        if (mceInit.content) {
          mceInit = mceInit.content;
        }

        if (window.wpActiveEditor) {
          // fix for new behaviour in WP 3.3
          this.options.set_item.mousedown( function() {
            wpActiveEditor = self.ui.textarea.attr("id");
          });
        }
      
        this.mce = true;
        this.mceId = this.ui.textarea.attr("id");

      
        this.mce_height = this.ui.textarea.innerHeight();
        this.mce_width = this.ui.textarea.innerWidth();
      
        this.mceOptions = jQuery.extend(true, {}, mceInit, { 
          setup : function(ed) {
          
            if (self.mce4) {
          
              ed.on("click", function(ed) {
                self.focus_field();
              });

              ed.on("keypress", function(ed) {
                self.focus_field();
                self.set_change();
              });
          
              if (self.saveOnChange) {
              
                ed.on("change", function() {
                  ed.save();
                });
            
              }
          
            } else {
            
              ed.onClick.add( function(ed, l) {
                self.focus_field();
              });

              ed.onKeyPress.add( function(ed, l) {
                self.focus_field();
                self.set_change();
              });

              if (self.saveOnChange) {
              
                ed.onChange.add( function(ed, l) {
                  ed.save();
                });
            
              }

          
            }
          
          }
        });
      
        this.mceOptions.mode = "exact";
        this.mceOptions.elements = this.mceId;


        this.ui.button_html.click(
          function() {
            if (!self.ui.button_html.hasClass("current")) {
              self.ui.textarea.wrap($('<div class="textarea-wrap"></div>'));
              self.ui.button_visual.removeClass("current");
              self.ui.button_html.addClass("current");
            
              self.mce_remove();
              self.pretty();
              if (self.using_cm()) {
                self.cm_add();
              }
            }

            self.focus_field();
          }
        );

        this.ui.button_visual.click(
          function() {
            if (!self.ui.button_visual.hasClass("current")) {
              self.ui.textarea.unwrap();
              self.ui.button_html.removeClass("current");
              self.ui.button_visual.addClass("current");

              if (self.using_cm()) {
                self.cm_remove();
              }
          
              self.mce_add(true);
            
            }
          
            self.focus_field();
          }
        );
      
      
        // add the media buttons
      
        if (self.mce4) {
        
        
          this.mceOptions.toolbar1 = "mp_media," + this.mceOptions.toolbar1;
        
          if (this.ui_options.mce_blockformats) {
            this.mceOptions.block_formats = this.ui_options.mce_blockformats;
          }
        
          if (this.ui_options.mce_styles) {
  
            // simualate the theme_advanced_styles dropdown in TinyMCE 3
          
            // build a list of label = class names
          
            var classes = [];
          
            var nv = this.ui_options.mce_styles.split(/\n|;/g);
          
            $.each(nv, function(index, item) {
            
              var parts = item.split("=");
            
              if (parts.length == 2) {
                classes.push({ title: parts[0], classes: parts[1] });
              } else if (parts.length == 1) {
                if ($.trim(item) != "") {
                  classes.push({ title: parts[0], classes: parts[0] });
                }
              }
            
            });
          
            if (classes.length) {
              self.mceOptions.style_formats = [];  
              
              $.each( classes, function(index, item) {
                self.mceOptions.style_formats.push({ title: item.title, selector: 'p,h1,h2,h3,h4,h5,h6,b,i,strong,em,ul,ol,li', inline: "span", classes: item.classes });
              });
            
            }
          
      
      
          
            var addStyleSelect = true;
      
            if (this.mceOptions.toolbar1 && this.mceOptions.toolbar1.match(/styleselect/)) {
              addStyleSelect = false;
            }

            if (this.mceOptions.toolbar2 && this.mceOptions.toolbar2.match(/styleselect/)) {
              addStyleSelect = false;
            }

            if (this.mceOptions.toolbar3 && this.mceOptions.toolbar3.match(/styleselect/)) {
              addStyleSelect = false;
            }

            if (addStyleSelect) {
              if (this.mceOptions.toolbar2) {
                this.mceOptions.toolbar2 = this.mceOptions.toolbar2.replace(/formatselect/, "formatselect,styleselect");
              } else if (this.mceOptions.toolbar) {
                this.mceOptions.toolbar = this.mceOptions.toolbar.replace(/formatselect/, "formatselect,styleselect");
              }
      
            }
      
          }
        
        
        } else {
        
          this.mceOptions.theme_advanced_buttons1 = "mp_media,|," + this.mceOptions.theme_advanced_buttons1;
    
          if (this.ui_options.mce_blockformats) {
            this.mceOptions.theme_advanced_blockformats = this.ui_options.mce_blockformats;
          }
      
          if (this.ui_options.mce_styles) {
            this.mceOptions.theme_advanced_styles = this.ui_options.mce_styles.split(/\n|;/g).join(";");
        
            var addStyleSelect = true;
        
            if (this.mceOptions.theme_advanced_buttons1 && this.mceOptions.theme_advanced_buttons1.match(/styleselect/)) {
              addStyleSelect = false;
            }

            if (this.mceOptions.theme_advanced_buttons2 && this.mceOptions.theme_advanced_buttons2.match(/styleselect/)) {
              addStyleSelect = false;
            }

            if (this.mceOptions.theme_advanced_buttons3 && this.mceOptions.theme_advanced_buttons3.match(/styleselect/)) {
              addStyleSelect = false;
            }

            if (addStyleSelect) {
              if (this.mceOptions.theme_advanced_buttons2) {
                this.mceOptions.theme_advanced_buttons2 = this.mceOptions.theme_advanced_buttons2.replace(/formatselect/, "formatselect,styleselect");
              } else if (this.mceOptions.theme_advanced_buttons) {
                this.mceOptions.theme_advanced_buttons = this.mceOptions.theme_advanced_buttons.replace(/formatselect/, "formatselect,styleselect");
              }
        
            }
      
          }
        
        }



        // check for readonly
        this.mceOptions.readonly = this.is_readonly();
      
        // remove the fullscreen plug-in, not sure how to support this yet....
      
        if (this.mceOptions.theme_advanced_buttons1) {
          this.mceOptions.theme_advanced_buttons1 = this.mceOptions.theme_advanced_buttons1.replace(/,fullscreen/, '');
          this.mceOptions.theme_advanced_buttons1 = this.mceOptions.theme_advanced_buttons1.replace(/,wp_fullscreen/, '');
        }
    
        var h = parseInt(this.ui_options.height);
      
        if (h && h > 60) {
          this.mceOptions.height = h;
        }
    
        if (self.mce4) {
          self.mceOptions.resize = true;
          self.mceOptions.wpautop = false;
        } else {
          self.mceOptions.theme_advanced_resizing = true;
        }
      
        this.mceOptions.init_instance_callback = function(inst) {
        
          // remove the wpautop stuff (hope this is maintainable, since I can't find ANY OTHER WAY!!)
        
          if (!self.mce4) {
            inst.onSaveContent.listeners = [];
          }
        
          var mceresize = function(e) {

            if (e && e.currentTarget && e.currentTarget.frameElement) {
              var $frame = $(e.currentTarget.frameElement);
          
              self.mce_height = $frame.innerHeight();
              self.mce_width = $frame.innerWidth();
            
              self.ui.textarea.css("height", self.mce_height + "px");
            }          
          
          };

          if (self.mce4) {
          
            // remove fullscreen plugin
            self.element.find("div.mce-wp-fullscreen").remove();
            //inst.on('resize', mceresize);
          
          } else {
            //tinymce.dom.Event.add(inst.getWin(), 'resize', mceresize);
          }
        
        };
      
        if (!self.mce4) {
          // old style of re-initializing tinyMCE. THis is now removed for the version 4 editor (WP 3.9)
        
      		try { // wp sometimes throws errors that I think we can ignore
          	tinyMCE.init(this.mceOptions);
        	} catch(e) {
            console.log(e);
    			}
      
        }
    

        if (this.ui.button_visual.hasClass("current")) {
          if (self.mce4) {
            self.mce_add();
          }
        } else {
          this.ui.textarea.wrap($('<div class="textarea-wrap"></div>'));
          self.pretty();
        
          if (self.using_cm()) {
            self.cm_add();
          }
        
        }
    	
			
  			// patch to stop tinymce breaking when using sortable metaboxes
    
      	var $sortables = self.element.parents(".ui-sortable").add($('#normal-sortables,#advanced-sortables'));
			
  			  $sortables.each( function() {
			
  			  var $sortable = $(this);
			    
    			if (!$sortable.data("mce-dragfix")) {
					
    				$sortable.data("mce-dragfix", true);
				  
    	      $sortable.bind({

    					sortstart: function(event, ui) {
              
                var item = ui.item.eq(0);
              
                if (item.hasClass("postbox") || item.hasClass("mp-set-item")) {
                
    						  var $set_item = $(event.originalEvent.target).closest(".mp-set-item");
        			
    						  var $fields;
						    
    						  if ($set_item.length) {
    						    $fields = $set_item.find(".mpft-visual-editor");
    					    } else {
    						    $fields = $(ui.item).closest(".postbox").find(".mpft-visual-editor");
    				      }

      						$fields.each( function() {
							
      							var $field = $(this);
							  
    							  if ($field.data("loaded")) {
    							    if ($field.mp_field('ui', 'mce_active')) {
                    		$field.mp_field('ui', 'mce_remove');
        							}
    							  }
							  
      						});
						
                }
              
              },

    	        sortstop: function(event, ui) {
						  
                var item = ui.item.eq(0);
              
                if (item.hasClass("postbox") || item.hasClass("mp-set-item")) {
              
      						var $set_item = $(event.originalEvent.target).closest(".mp-set-item");

    						  var $fields;

    						  if ($set_item.length) {
    						    $fields = $set_item.find(".mpft-visual-editor");
    					    } else {
    						    $fields = $(ui.item).closest(".postbox").find(".mpft-visual-editor");
    				      }
						
      						$fields.each( function() {
							
      							var $field = $(this);
							  
    							  if ($field.data("loaded")) {
                
    							    if ($field.mp_field('ui', 'mce_active')) {
        								$field.mp_field('ui', 'mce_add', true);
        							}
							
    							  }
							  
      						});
              
                }
            
    	        }
      
    	      });
          }
        
  			});
			
      } else {
        
        self.cache_ui();
        
      } // endif tinymce
      
  	},
    
		mce_active: function() {
			return this.ui && this.ui.button_visual && this.ui.button_visual.hasClass("current");
		},
		
    using_cm: function() {
      return this.ui_options.html_editor == "cm";
    },
    
    cm_remove: function() {
      var self = this;
      
      if (self.codeMirror) {
        self.codeMirror.toTextArea();
      }    
    },
    
    pretty: function() {
      var self = this;
      
      var wrapChars = 80;
      
      if (self.mce_width) {
        wrapChars = Math.round(self.mce_width / 9.3);
      }

      var val = self.ui.textarea.val();
      
      val = val.replace(/<\/(p|div|li|ul|ol)>/g, "\n</$1>\n")
        .replace(/<img/g, "\n<img")
        .replace(/\/>/g, "/>\n")
        .replace(/<(p|div|ul|ol|li)([^>]*)>/g, "<$1$2>\r")
        .replace(/<(h1|h2|h3|h4|h5|h6)>/g, "\n<$1>")
        .replace(/<\/(h1|h2|h3|h4|h5|h6)>/g, "</$1>\n")
        .replace(/\n\s(<a)/g, "\n$1")
        .replace(/<br\s?\/>/g, "<br />\n")
        .replace(/<br\s?\/>\n\n/g, "<br />\n");
               
      self.ui.textarea.val(val);

    },
    
    cm_add: function() {
      var self = this;
      
      self.codeMirror = CodeMirror.fromTextArea(self.ui.textarea.get(0), { styleActiveLine: true, readOnly: self.is_readonly(), theme: self.ui_options.cm_theme, mode: "htmlmixed", lineWrapping: true, lineNumbers: true, enterMode: 'flat', electricChars: false });

      if (self.mce_height) {
        self.codeMirror.setSize(null, self.mce_height + 76);
				self.focus();
      }

    },
    
    mce_remove: function(focus) {
      
      this.mce = false;

      if (this.mce4) {
        tinymce.EditorManager.execCommand('mceRemoveEditor', false, this.mceId);        
      } else {
        tinyMCE.execCommand('mceRemoveControl', false, this.mceId);        
      }

      if (this.ui && this.ui.textarea) {

        this.ui.textarea.css("margin-bottom", "21px");
        
        if (focus) {
          this.ui.textarea.focus();
        }

      }
        
    },
    
    mce_add: function(focus) {
      this.mce = true;
      
      if (this.mce4) {
        
        this.ed = new tinymce.Editor(this.mceId, this.mceOptions, tinymce.EditorManager);
        this.ed.on("init", function() {
            
        });
        
        this.ed.render();
        
        
      } else {
        tinyMCE.execCommand('mceAddControl', true, this.mceId); 
      }

      tinyMCE.execCommand('mceAddControl', true, this.mceId); 
      
      if (focus) {
        tinyMCE.execCommand('mceFocus', false, this.mceId);
      }
    },
    
    get_content: function() {
      var self = this;
      var val;
      
      if (self.ui.button_html.hasClass("current")) {
        if (self.codeMirror) {
          val = self.codeMirror.getValue();
        } else {
          val = self.ui.textarea.val();
        }
        
      } else {
        val = tinyMCE.get(this.mceId).getContent();
      }
      
      return val;
    },
    
    strip_value: function(val) {
      return $.trim( val.replace(/<[^>]*>/ig, "&nbsp;").replace(/^(&nbsp;)+/g, "").replace(/(&nbsp;){2,}/g, "&nbsp;") );
    },
    
    wordwrap: function( str, width, brk, cut, noempty ) {

        brk = brk || '\n';
        width = width || 75;
        cut = cut || false;

        if (!str) { return str; }

        var regex = '.{1,' +width+ '}(\\s|$)' + (cut ? '|.{' +width+ '}|.+$' : '|\\S+?(\\s|$)');

        var ret = str.match( RegExp(regex, 'g') ).join( brk );
        
        return ret;
        
    },
    
    is_empty: function() {
      return this.value() == "";
    },
    
    value: function() {
      
      var self = this;
      self.cache_ui();
      
      if (self.mce) {
        return this.get_content();
      } else {
        return this.element.find("textarea").val();
      }
    },

    set_value: function(value) {
      var self = this;
      this.cache_ui();
      if (this.expanded()) {
        
        if (self.ui.button_html.hasClass("current")) {
          if (self.codeMirror) {
            self.codeMirror.setValue(value);
          } else {
            self.ui.textarea.val(value);
          }

        } else {
          val = tinyMCE.get(this.mceId).setContent(value);
        }
        
      } else {
        this.element.find("textarea").val(value);
      }
    },
    
    summary: function() {
	
			var val = this.strip_value(this.value());
      // remove shorttags (more readable summary) 
      
      var content = $.trim(val.replace(/\[[^\]]*\]/ig, '').replace(/^\s*/ig, '').replace(/^(&nbsp;)+/g, ""));
      
			if (content == "") {
				content = val;
			}
			
      return content;
    }


  });

})(jQuery);