function HTMLMemo(sys, formID, code, posX, posY, width, height, description, value) {
  this.create(sys, formID, code, posX, posY, width, height, description, value);
  this.type = 1;
  this.report = false;
  this.wrap = false;
}

HTMLMemo.inherits(HTMLEdit);

HTMLMemo.prototype.name = 'HTMLMemo';
HTMLMemo.prototype.tabable = true;
HTMLMemo.prototype.tagName = 'edit';
HTMLMemo.prototype.tabKeys = [9];

document["loadTime"] = 100;

HTMLMemo.prototype.designReport = function() {
  var mainDiv;
  var div = this.getDiv('WFRMemo'+this.code, this.posX, this.posY, this.width+(IE?2:0), this.height+(IE?2:0), 3, true);
  div.id  = "ReportMemo" + this.code;
  div.innerHTML = this.value;

  mainDiv = MM_findObj("lay");
  mainDiv.appendChild(div);
};

HTMLMemo.prototype.setReadOnly = function(v) {
  if (this.isRichText()) {
    this.readonly = v;
    this.reinitTinyMCE();
    visibleDiv(this.readonlyDiv, this.readonly);
    if (v) {
      this.input.setAttribute("readonly", "readonly");
      this.setRichTextBackgroundColor(this.bgColor ? this.bgColor : window.getComputedStyle(this.input).backgroundColor);
    } else {
      this.input.removeAttribute("readonly");
      this.setRichTextBackgroundColor(this.bgColor ? this.bgColor : window.getComputedStyle(this.input).backgroundColor);
    }
  } else {
    this.callMethod(HTMLEdit, "setReadOnly", [v]);
  }
};

HTMLMemo.prototype.setReadOnlyDiv = function(v) {
  var divCorrection;
  if (this.richText) {
    //Basico = 62px || Avancado = 115px
    divCorrection = this.richText == 1 ? 62 : 115;
    if (!this.readOnlyDiv) {
      this.readOnlyDiv = this.getDiv('ReadOnlyDiv'+this.code, 0, 0, this.width, this.height, 100005, true);
      this.readOnlyDiv.innerHTML = '<table width=100% height=100%><tr><td>&nbsp;</td></tr></table>';
    }
    if (!v) {
      if (containsNode(this.div, this.readOnlyDiv)) {
        this.div.removeChild(this.readOnlyDiv);
      }
    } else {
      if (!containsNode(this.div, this.readOnlyDiv)) {
        this.div.appendChild(this.readOnlyDiv);
      }
    }
  } else {
    this.callMethod(HTMLElementBase, "setReadOnlyDiv", [v]);
  }
};


HTMLMemo.prototype.hasEmptyValue = function() {
  if(this.isRichText()){
   return tinyMCE.get(this.input.name).getContent()  == '';
  }else{
   return this.getValue()  == '';
  }
}

HTMLMemo.prototype.setEnabled = function(v) {
  if (this.richText) {
    this.enabled = v;
    this.reinitTinyMCE();    
    this.setReadOnlyDiv(!v);
    if (!this.enabled) {
      try{
        tinyMCE.DOM.setAttrib(tinyMCE.get(this.input.name).getBody(), "class", "unselectable");
      }catch(e){
        //
      }
      if (containsNode(this.context, this.btdiv)) {
        this.context.removeChild(this.btdiv);
      }
      this.input.setAttribute("disabled", "disabled");
      this.setRichTextBackgroundColor(this.bgColor ? this.bgColor : window.getComputedStyle(this.input).backgroundColor);
    } else {
      try{
        tinyMCE.DOM.removeClass(tinyMCE.get(this.input.name).getBody(), "unselectable");
      }catch(e){
        //nothing
      }
      if (this.type == 2 && !containsNode(this.context, this.btdiv)) {
        this.context.appendChild(this.btdiv);
      }
      this.input.removeAttribute("disabled");
      this.setRichTextBackgroundColor(this.bgColor ? this.bgColor : window.getComputedStyle(this.input).backgroundColor);
    }
  } else {
    this.callMethod(HTMLEdit, "setEnabled", [v]);
  }
};

HTMLMemo.prototype.designInput = function(doc, name, value) {
  this.input = document.createElement("TEXTAREA");
  this.input.setAttribute('wrap', (this.wrap) ? 'soft' : 'off');

  if (this.placeholder) {
    this.input.placeholder = this.placeholder;
  }

  if (!name) {
    this.input.name = 'WFRInput' + this.code;
    this.input.id = 'WFRInput' + this.code;
  } else {
    this.input.name = name;
    this.input.id = name;
  }
  
  if((this.richText == 1) || (this.richText == 2)){
    this.input.style.opacity = 0;
  }
  
  if (this.richText == 2){
      this.input.style.height = (this.height - 58) + "px";
  }else if (this.richText == 1){
    this.input.style.height = (this.height - 31) + "px";
  }else{
  this.input.style.height = this.height + "px";
  }
  this.input.style.width = this.width + "px";
  
  if (!value) {
    this.input.value = this.value;
  } else {
    this.input.value = value;
  }
};

HTMLMemo.prototype.beforeComponentDesign = function(doc) {
};

HTMLMemo.prototype.design = function(doc, tabControl) {
  this.doc = doc;
  if (this.description != '') {
    this.div = this.getDiv('WFRComponent' + this.code, this.posX, this.posY, this.width, this.height + this.labelDivHeight, this.zindex, !this.isRichText());
    this.labeldiv = this.getDiv('WFRComponentLabel' + this.code, 0, -1 * this.labelDivHeight, 0, this.labelDivHeight, 2, !this.isRichText());

    this.label = document.createElement("font");
    this.label.innerHTML = this.decorateRequired(this.description.replace(/\s/g, '&nbsp;'), this.required);
    this.labeldiv.appendChild(this.label);
    this.context = this.getDiv('WFRComponentContext' + this.code, 0, 0, this.width, this.height, 2, true);
  } else
    this.div = this.getDiv('WFRComponent' + this.code, this.posX, this.posY, this.width, this.height, this.zindex, !this.isRichText());
  this.div.className = this.name;

  if(this.labeldiv) {
    this.div.appendChild(this.labeldiv);
  }
  if(this.context){
    this.div.appendChild(this.context);
  }
  else{
    this.context = this.div;
  }

  this.designComponent(doc);
  doc.appendChild(this.div);

  if (this.description && this.labelPosition) {
    this.labeldiv.setAttribute("style", this.labeldiv.getAttribute("style")  + this.fontDescStyle);
  
    if (this.labelPosition == '1') {//Alinhar abaixo do componente  
      this.labeldiv.style.width = this.context.style.width;
      this.labeldiv.style.height = "";
      this.labeldiv.style.top = "calc(100% - 12pt)";
      this.labeldiv.id = "labelbottom";
    } else if (this.labelPosition == '2') {//Alinhar a esquerda do componente
      var tab = d.t.getTabByName(this.getTabName());
      var display = tab.div.style.display;
      tab.div.style.display = "block";
      this.labeldiv.style.right = "calc(100% + 3px)";
      this.labeldiv.style.left = "";
      this.labeldiv.style.textAlign = "right";
      this.labeldiv.style.height = "";
      this.labeldiv.style.top = "";
      tab.div.style.display = display;   
    } else if (this.labelPosition == '3') {//Alinhar a direita do componente
      this.labeldiv.className="labelright";
      this.labeldiv.style.left = "calc(100% + 2px)";
      this.labeldiv.style.textAlign = "left";
      this.labeldiv.style.height = "";
      this.labeldiv.style.top = "";
    } else{
      this.labeldiv.style.height = "";   
      this.labeldiv.style.top = ((parseInt(this.labeldiv.style.fontSize)) * - 1.333333) - 5 + "px";  
    }
  }

  if (this.label) {
    this.label.draggable = false;
    this.label.resizable = false;
  }

  this.init(tabControl);
};

HTMLMemo.prototype.afterComponentDesign = function(doc) {
  if (this.isRichText()) {
    this.timeout(this.richTextLoad, document["loadTime"]);
    document["loadTime"] = document["loadTime"] + 200;
  }
};

HTMLMemo.prototype.adjustReadOnlyDivDimensions = function() {
  var textarea;
  var width;
  var height;
  try {
    textarea = tinyMCE.get(this.input.name);
    width = textarea.getContainer().offsetWidth;
    height = textarea.getContainer().offsetHeight;
    if (width > 0 && height > 0) {
      this.readonlyDiv.style.width = Math.max(this.getWidth(), width);
      this.readonlyDiv.style.height = Math.max(this.getHeight(), height);
      return true;
    }
  } catch(e){
    //Ignora erros
  }
  this.timeout(this.adjustReadOnlyDivDimensions, 100);
};

HTMLMemo.prototype.validateDataType = function(focus) {
  var r = this.callMethod(HTMLElementBase, "validateDataType", [focus]);

  if (r && this.maxlength) {
    if (this.getValue().length > this.maxlength) {
      interactionError(getLocaleMessage("INFO.MEMO_MAXIMUM_CHARACTERS", (this.description ? this.description : this.id), this.maxlength), focus ? (function(e) {e.getFocus(true); }) : null, focus ? [this] : null);
      return false;
    }
  }
  return r;
};

HTMLMemo.prototype.keyupAction = function(e){
  var r = this.callMethod(HTMLElementBase, "keyupAction", [e]);
  var value;
  var valueSizeLimited;
  if (r && this.maxlength) {
    value = this.getValue();
    valueSizeLimited = this.defineTextByLength(e);
    if (value != valueSizeLimited) {
      this.setValue(valueSizeLimited);
    }
  }
};

HTMLMemo.prototype.defineTextByLength = function(e) {
  var value = this.getValue();

  if (value.length > this.maxlength) {
    value = value.substring(0, this.maxlength);
  }

  return value;
};

HTMLMemo.prototype.richTextLoad = function () {
  
  //Cria Objeto superior para a tabulação.
  var inputAbove = document.createElement("TEXTAREA");
  inputAbove.style = "height: 1px; opacity:0; position: absolute";
  inputAbove.id = this.input.name + 'Tab';
  this.div.insertBefore(inputAbove, this.div.childNodes[0]);
  inputAbove.addEventListener("focus", function(){ tabAsyncMemo(o, true); })
  
  //Regras do Componente
  var disableBar = !this.enabled || this.readonly === true ? true : false;
  var onfocus = this.onfocus;
  var onclick = this.onclick;
  var onchange = this.onchange;
  var onkeypress = this.input['onkeypress'];
  var onblur = this.onblur;
  var tinymceLangs = {
    "en_US": "en",
    "es_ES": "es",
    "fr_FR": "fr_FR",
    "pt_BR": "pt_BR"
  };
  var tinymceOptions = {
    "toolbar_items_size": "small",
    "language": tinymceLangs[resources_locale],
    "mode": "none",
    "statusbar": false,
    "convert_fonts_to_spans": false,
    "inline_styles": false,
    "verify_html": false,
    "height": this.input.style.height,
    "readonly": disableBar,  //desabilita toda a barra
    "init_instance_callback" : function(editor) {
      editor.on("focus", onfocus),
      editor.on("click", onclick),
      editor.on("change", onchange),
      editor.on("keypress", onkeypress),
      editor.on("blur", onblur)
    }
  };


  window.tinyMCE_GZ = {loaded: true};

  webrun.include("components/tinymce/tinymce.min.js");

  tinymce.documentBaseURL = window.location.href.replace(/[\?#].*$/, "").replace(/[\/\\][^\/]+$/, "");

  if (!/[\/\\]$/.test(tinymce.documentBaseURL)) {
    tinymce.documentBaseURL += "/";
  }

  tinymce.suffix = ".min";
  tinymce.documentBaseURL += "components/tinymce";
  tinymce.baseURL = new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.documentBaseURL);
  tinymce.EditorManager.baseURI = new tinymce.util.URI(tinymce.baseURL);
  tinymce.dom.Event.domLoaded = true;  

  if (this.richText == '1') {
    tinymceOptions.menubar = false;
    tinymceOptions.toolbar = " bold italic underline strikethrough | undo redo | removeformat | bullist numlist";
  } else if (this.richText == '2') {
    tinymceOptions.relative_urls = false;
    tinymceOptions.menu = "none";
    tinymceOptions.plugins = "hr,image,anchor,preview,code,paste,textcolor,link";
    tinymceOptions.toolbar = [
      "fontselect fontsizeselect forecolor | bold italic underline strikethrough hr | " +
      "alignleft aligncenter alignright alignjustify | link unlink",
      "bullist numlist | outdent indent | undo redo | " +
      "anchor image removeformat code | cut copy paste | table | subscript superscript"
    ];
  }
  
  //Chamada no arquivo wfr.js - tabAsyncMemo;
  var o = this;
  this.input.addEventListener("focus", function(){ tabAsyncMemo(o, false); }); 

  tinyMCE.init(tinymceOptions);

  if (this.readonly) {
    tinymce.EditorManager.once('AddEditor', function (editorProps) {
      editorProps.editor.on('keydown', function (event) {
        var keyCode = event.which || event.keyCode;
        //Nao bloqueia Ctrl + C
        if (!(keyCode === 67 && event.ctrlKey || keyCode === 82 && event.ctrlKey)) {
          event.preventDefault();
        }
      });
    });
  }

  tinyMCE.execCommand('mceAddEditor', false, this.input.name);

  timeout(visibleDiv, 0, [this.div, this.visible]);
    

  if (this.labeldiv) {
    this.timeout(function () {
      this.createLabelDiv();
      this.div.appendChild(this.labeldiv);
    }, 200);
  }

  if (this.wrap && this.richText) {
    this.setRichTextWordWrap('break-word');
  }
 this.input.style.top = '0px';
 this.input.style.zIndex = '-1';
 this.input.style.position = 'absolute';
};

HTMLMemo.prototype.onInitRichText = function(ed) {
  this.defineRichTextEvents(ed);

  //Caso isolado para, quando um componente Texto rico possua o evento ao modificar
  //o mesmo nao seja disparado na primeira vez em que for feito o onBlur.
  if (this.onchange && !this.isDBAware()) {
    this.value = this.getValue();
  }
};

HTMLMemo.prototype.defineRichTextEvents = function(ed) {
  var self;
  var action;
  //Definicao do evento onBlur no texto rico.
  //Chamado depois que o componente é carregado.
  //Esta chamada está definida no setup do init() do componente.
  var caller = (isFirefox ? ed.contentDocument : ed.contentWindow);
  if (caller.addEventListener) { //Firefox, Chrome
    self = this;
    caller.addEventListener('blur', function() {
      self.onBlurRichTextAction();
    }, false);
  } else { //IE
    action = new HTMLAction(this.onBlurRichTextAction, this);
    this.attachEvent(caller, 'blur', action);
  }
};

HTMLMemo.prototype.onBlurRichTextAction = function(ed) {
  var r;
  if (this.onchange) {
    if (this.value != this.getValue()) {
      this.setValue(this.getValue());
    }
  }
  if (this.onblur) {
    this.onblur();
  }
  r = this.enabled && this.visible && !this.readonly && !this.resizable && !this.draggable;
  if (this.doc) r = r && isVisibleDiv(this.doc);
  if (r) {
    this.setRichTextBorderColor('1px solid #CCC');
    this.setRichTextBackgroundColor('#FFFFFF');
  }
  this.focuzed = false;
};

HTMLMemo.prototype.focus = function() {
  var r = this.enabled && this.visible && !this.readonly && !this.resizable && !this.draggable;
  var richTextObj;

  if (this.doc) r = r && isVisibleDiv(this.doc);
  if (r) {
    // O memo, quando definido como RichText, tem um comportamento diferente para focar no componente.
    if (this.isRichText()) {
      //Define bordas e backgroundColor quando focado
      //this.setRichTextBorderColor('1px solid #06C');
      //Aplica a cor para o componente em foco.
    //this.setRichTextBackgroundColor('#E6F2FF');

      richTextObj = tinyMCE.get(this.input.name);
      if (richTextObj && richTextObj.focus) {
        richTextObj.focus();
      }
      this.focuzed = true;
    } else if (this.input) {
      this.input.focus();
      this.focuzed = true;
    }
  }

  return r;
};

HTMLMemo.prototype.setRichTextBorderColor = function() {};

HTMLMemo.prototype.setRichTextWordWrap = function(v) {
  try{    
    this.richTextEditor.getBody().style.wordWrap = v;
  } catch(e) {
    this.timeout(function(){this.setRichTextWordWrap(v)},100);
  }
};

HTMLMemo.prototype.setRichTextBackgroundColor = function(v) {
  try{
    tinyMCE.get(this.input.name).getBody().setAttribute("style","background-color:" + v);
  } catch(e) {
    this.timeout(function(){this.setRichTextBackgroundColor(v)},100);
  }
};

HTMLMemo.prototype.setValue = function(value, checkDependences) {
  if (this.isRichText()) {
    this.setRichTextValue(value, checkDependences);
  } else {
    this.callMethod(HTMLElementBase, "setValue", [value, checkDependences]);
  }
};

HTMLMemo.prototype.setRichTextValue = function(value, checkDependences) {
  var tinyComponent = tinyMCE.get(this.input.name);
  if (tinyComponent) {
    value = normalizeRuleParam(value, true);
    tinyComponent.setContent(value);
    if (this.onchange && (value != this.value)) {
      this.value = value;
      this.onchange();
    }
    this.value = normalizeRuleParam(this.getValue());
  } else {
    this.callMethod(HTMLElementBase, "setValue", [value, checkDependences]);
  }
};

HTMLMemo.prototype.getValue = function() {
  if (this.isRichText()) {
    return this.getRichTextValue();
  } else {
    return this.input.value;
  }
};

HTMLMemo.prototype.getRichTextValue = function() {
  if (tinyMCE.get(this.input.name)) {
    return tinyMCE.get(this.input.name).getContent({format: "raw"});
  } else {
    return null;
  }
};

HTMLMemo.prototype.isRichText = function() {
  return (this.richText == "1" || this.richText == "2");
};

HTMLMemo.prototype.reinitTinyMCE = function() {
  try{ //reinicia o tinyMCE
    document.getElementById(this.input.name + 'Tab').parentElement.removeChild(document.getElementById(this.input.name + 'Tab'));
    tinyMCE.execCommand('mceRemoveEditor', false, this.input.name);
    this.richTextLoad();
  }catch(e){
    //Abafa
  }
};