/*
 * ext-foreignobject.js
 *
 * Licensed under the Apache License, Version 2
 *
 * Copyright(c) 2010 Jacques Distler 
 * Copyright(c) 2010 Alexis Deveria 
 *
 */

svgEditor.addExtension("foreignObject", function(S) {
    var svgcontent = S.svgcontent,
      addElem = S.addSvgElementFromJson,
      selElems,
      svgns = "http://www.w3.org/2000/svg",
      xlinkns = "http://www.w3.org/1999/xlink",
      xmlns = "http://www.w3.org/XML/1998/namespace",
      xmlnsns = "http://www.w3.org/2000/xmlns/",
      se_ns = "http://svg-edit.googlecode.com",
      htmlns = "http://www.w3.org/1999/xhtml",
      mathns = "http://www.w3.org/1998/Math/MathML",
      editingforeign = false,
      svgdoc = S.svgroot.parentNode.ownerDocument,
      started,
      newFO;
      
      
    var properlySourceSizeTextArea = function(){
      // TODO: remove magic numbers here and get values from CSS
      var height = $('#svg_source_container').height() - 80;
      $('#svg_source_textarea').css('height', height);
    };

    function showPanel(on) {
      var fc_rules = $('#fc_rules');
      if(!fc_rules.length) {
        fc_rules = $('<style id="fc_rules"><\/style>').appendTo('head');
      } 
      fc_rules.text(!on?"":" #tool_topath { display: none !important; }");
      $('#foreignObject_panel').toggle(on);
    }

    function toggleSourceButtons(on) {
      $('#tool_source_save, #tool_source_cancel').toggle(!on);
      $('#foreign_save, #foreign_cancel').toggle(on);
    }
    
      
    // Function: setForeignString(xmlString, elt)
    // This function sets the content of element elt to the input XML.
    //
    // Parameters:
    // xmlString - The XML text.
    // elt - the parent element to append to
    //
    // Returns:
    // This function returns false if the set was unsuccessful, true otherwise.
    function setForeignString(xmlString) {
      var elt = selElems[0];
      try {
        // convert string into XML document
        var newDoc = Utils.text2xml('<svg xmlns="'+svgns+'" xmlns:xlink="'+xlinkns+'">'+xmlString+'</svg>');
        // run it through our sanitizer to remove anything we do not support
        S.sanitizeSvg(newDoc.documentElement);
        elt.parentNode.replaceChild(svgdoc.importNode(newDoc.documentElement.firstChild, true), elt);
        S.call("changed", [elt]);
        svgCanvas.clearSelection();
      } catch(e) {
        console.log(e);
        return false;
      }
  
      return true;
    };

    function showForeignEditor() {
      var elt = selElems[0];
      if (!elt || editingforeign) return;
      editingforeign = true;
      toggleSourceButtons(true);
      elt.removeAttribute('fill');

      var str = S.svgToString(elt, 0);
      $('#svg_source_textarea').val(str);
      $('#svg_source_editor').fadeIn();
      properlySourceSizeTextArea();
      $('#svg_source_textarea').focus();
    }
    
    function setAttr(attr, val) {
      svgCanvas.changeSelectedAttribute(attr, val);
      S.call("changed", selElems);
    }
    
    
    return {
      name: "foreignObject",
      svgicons: "extensions/foreignobject-icons.xml",
      buttons: [{
        id: "tool_foreign",
        type: "mode",
        title: "Foreign Object Tool",
        events: {
          'click': function() {
            svgCanvas.setMode('foreign')
          }
        }
      },{
        id: "edit_foreign",
        type: "context",
        panel: "foreignObject_panel",
        title: "Edit ForeignObject Content",
        events: {
          'click': function() {
            showForeignEditor();
          }
        }
      }],
      
      context_tools: [{
        type: "input",
        panel: "foreignObject_panel",
        title: "Change foreignObject's width",
        id: "foreign_width",
        label: "w",
        size: 3,
        events: {
          change: function() {
            setAttr('width', this.value);
          }
        }
      },{
        type: "input",
        panel: "foreignObject_panel",
        title: "Change foreignObject's height",
        id: "foreign_height",
        label: "h",
        events: {
          change: function() {
            setAttr('height', this.value);
          }
        }
      }, {
        type: "input",
        panel: "foreignObject_panel",
        title: "Change foreignObject's font size",
        id: "foreign_font_size",
        label: "font-size",
        size: 2,
        defval: 16,
        events: {
          change: function() {
            setAttr('font-size', this.value);
          }
        }
      }
      
      
      ],
      callback: function() {
        $('#foreignObject_panel').hide();

        var endChanges = function() {
          $('#svg_source_editor').hide();
          editingforeign = false;
          $('#svg_source_textarea').blur();
          toggleSourceButtons(false);
        }

        // TODO: Needs to be done after orig icon loads
        setTimeout(function() {        
          // Create source save/cancel buttons
          var save = $('#tool_source_save').clone()
            .hide().attr('id', 'foreign_save').unbind()
            .appendTo("#tool_source_back").click(function() {
              
              if (!editingforeign) return;

              if (!setForeignString($('#svg_source_textarea').val())) {
                $.confirm("Errors found. Revert to original?", function(ok) {
                  if(!ok) return false;
                  endChanges();
                });
              } else {
                endChanges();
              }
              // setSelectMode();  
            });
            
          var cancel = $('#tool_source_cancel').clone()
            .hide().attr('id', 'foreign_cancel').unbind()
            .appendTo("#tool_source_back").click(function() {
              endChanges();
            });
          
        }, 3000);
      },
      mouseDown: function(opts) {
        var e = opts.event;
        
        if(svgCanvas.getMode() == "foreign") {

          started = true;
          newFO = S.addSvgElementFromJson({
            "element": "foreignObject",
            "attr": {
              "x": opts.start_x,
              "y": opts.start_y,
              "id": S.getNextId(),
              "font-size": 16, //cur_text.font_size,
              "width": "48",
              "height": "20",
              "style": "pointer-events:inherit"
            }
          });
          var m = svgdoc.createElementNS(mathns, 'math');
          m.setAttributeNS(xmlnsns, 'xmlns', mathns);
          m.setAttribute('display', 'inline');
          var mi = svgdoc.createElementNS(mathns, 'mi');
          mi.setAttribute('mathvariant', 'normal');
          mi.textContent = "\u03A6";
          var mo = svgdoc.createElementNS(mathns, 'mo');
          mo.textContent = "\u222A";
          var mi2 = svgdoc.createElementNS(mathns, 'mi');
          mi2.textContent = "\u2133";
          m.appendChild(mi);
          m.appendChild(mo);
          m.appendChild(mi2);
          newFO.appendChild(m);
          return {
            started: true
          }
        }
      },
      mouseUp: function(opts) {
        var e = opts.event;
        if(svgCanvas.getMode() == "foreign" && started) {
          var attrs = $(newFO).attr(["width", "height"]);
          keep = (attrs.width != 0 || attrs.height != 0);
          svgCanvas.addToSelection([newFO], true);

          return {
            keep: keep,
            element: newFO
          }

        }
        
      },
      selectedChanged: function(opts) {
        // Use this to update the current selected elements
        selElems = opts.elems;
        
        var i = selElems.length;
        
        while(i--) {
          var elem = selElems[i];
          if(elem && elem.tagName == "foreignObject") {
            if(opts.selectedElement && !opts.multiselected) {
              $('#foreign_font_size').val(elem.getAttribute("font-size"));
              $('#foreign_width').val(elem.getAttribute("width"));
              $('#foreign_height').val(elem.getAttribute("height"));
            
              showPanel(true);
            } else {
              showPanel(false);
            }
          } else {
            showPanel(false);
          }
        }
      },
      elementChanged: function(opts) {
        var elem = opts.elems[0];
      }
    };
});
