// BEGIN FLOCK GPL
//
// Copyright Flock Inc. 2005-2009
// http://flock.com
//
// This file may be used under the terms of the
// GNU General Public License Version 2 or later (the "GPL"),
// http://www.gnu.org/licenses/gpl.html
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// END FLOCK GPL

const CI = Components.interfaces;

var EXPORTED_SYMBOLS = ["flockXMLEncode", "flockXMLDecode", "flockBreakLongText"];

/**
 * Encode special characters as XML character entities for inclusion in XML.
 */
function flockXMLEncode(aString) {
  // When encoding, do ampersands FIRST.
  return aString.replace(/&/g, "&amp;")
                .replace(/</g, "&lt;")
                .replace(/>/g, "&gt;")
                .replace(/\'/g, "&apos;")
                .replace(/\"/g, "&quot;");
}

/**
 * Decode XML character entities for presentation.
 */
function flockXMLDecode(aString) {
  if (aString) {
    // When decoding, do ampersands LAST.
    return aString.replace(/&lt;/g, "<")
                  .replace(/&gt;/g, ">")
                  .replace(/&apos;/g, "'")
                  .replace(/&#39;/g, "'")
                  .replace(/&quot;/g, '"')
                  .replace(/&#035;/g, "#")
                  .replace(/&amp;/g, "&");
  } else {
    return "";
  }
}

function flockBreakLongText(aDOMElement, aMax) {
  if (!aDOMElement) {
    return;
  }
  var doc = aDOMElement.ownerDocument;

  // Determine the best point at which to break a long word
  function bestBreakPoint(aWord) {
    // If there's a hyphen or certain other punctuation, break after that
    // (unless it's too close the beginning of the word)
    for (let i = aMax; i >= 10; i--) {
      switch (aWord.charAt(i)) {
        case "-":
        case "/":
        case ".":
        case "!":
        case "?":
        case ",":
        case ";":
        case ":":
          return i + 1;
      }
    }
    // We didn't find a good place, so just break at aMax
    return aMax;
  }

  // Break a long word up into smaller words
  function breakWord(aWord) {
    if (aWord.length <= aMax) {
      return aWord;
    }
    let bp = bestBreakPoint(aWord);
    return aWord.substr(0, bp) + " " + breakWord(aWord.substr(bp));
  }

  // Process a textNode
  function processTextNode(aTextNode) {
    let text = aTextNode.textContent;
    if (text.length <= aMax) {
      return;
    }
    var words = text.split(" ");
    for each (let word in words) {
      if (word.length > aMax) {
        text = text.replace(word, breakWord(word));
      }
    }
    aTextNode.textContent = text;
  }

  // Recursively iterate through the child nodes
  function iterateChildren(aElem) {
    for (let c = 0; c < aElem.childNodes.length; c++) {
      let child = aElem.childNodes.item(c);
      if (child instanceof CI.nsIDOMElement) {
        iterateChildren(child);
      } else {
        processTextNode(child);
      }
    }
  }

  iterateChildren(aDOMElement);
}
