/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* Copyright 2012 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

var Metadata = PDFJS.Metadata = (function MetadataClosure() {
  function fixMetadata(meta) {
    return meta.replace(/>\\376\\377([^<]+)/g, function(all, codes) {
      var bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g,
                                function(code, d1, d2, d3) {
        return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1);
      });
      var chars = '';
      for (var i = 0; i < bytes.length; i += 2) {
        var code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1);
        chars += code >= 32 && code < 127 && code != 60 && code != 62 &&
          code != 38 && false ? String.fromCharCode(code) :
          '&#x' + (0x10000 + code).toString(16).substring(1) + ';';
      }
      return '>' + chars;
    });
  }

  function Metadata(meta) {
    if (typeof meta === 'string') {
      // Ghostscript produces invalid metadata
      meta = fixMetadata(meta);

      var parser = new DOMParser();
      meta = parser.parseFromString(meta, 'application/xml');
    } else if (!(meta instanceof Document)) {
      error('Metadata: Invalid metadata object');
    }

    this.metaDocument = meta;
    this.metadata = {};
    this.parse();
  }

  Metadata.prototype = {
    parse: function Metadata_parse() {
      var doc = this.metaDocument;
      var rdf = doc.documentElement;

      if (rdf.nodeName.toLowerCase() !== 'rdf:rdf') { // Wrapped in <xmpmeta>
        rdf = rdf.firstChild;
        while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf')
          rdf = rdf.nextSibling;
      }

      var nodeName = (rdf) ? rdf.nodeName.toLowerCase() : null;
      if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes())
        return;

      var childNodes = rdf.childNodes, desc, namespace, entries, entry;

      for (var i = 0, length = childNodes.length; i < length; i++) {
        desc = childNodes[i];
        if (desc.nodeName.toLowerCase() !== 'rdf:description')
          continue;

        entries = [];
        for (var ii = 0, iLength = desc.childNodes.length; ii < iLength; ii++) {
          if (desc.childNodes[ii].nodeName.toLowerCase() !== '#text')
            entries.push(desc.childNodes[ii]);
        }

        for (ii = 0, iLength = entries.length; ii < iLength; ii++) {
          var entry = entries[ii];
          var name = entry.nodeName.toLowerCase();
          this.metadata[name] = entry.textContent.trim();
        }
      }
    },

    get: function Metadata_get(name) {
      return this.metadata[name] || null;
    },

    has: function Metadata_has(name) {
      return typeof this.metadata[name] !== 'undefined';
    }
  };

  return Metadata;
})();

@@ -2441,21 +2441,19 @@
 ar child
-Nodes
+ren
  = rdf.c
@@ -2473,33 +2473,43 @@
 sc, 
-namespace, entries, entry
+entry, name, i, ii, length, iLength
 ;%0A%0A 
@@ -2514,28 +2514,24 @@
 %0A      for (
-var 
 i = 0, lengt
@@ -2535,29 +2535,27 @@
 ngth = child
-Nodes
+ren
 .length; i %3C
@@ -2590,21 +2590,19 @@
  = child
-Nodes
+ren
 %5Bi%5D;%0A   
@@ -2686,30 +2686,8 @@
 e;%0A%0A
-        entries = %5B%5D;%0A
     
@@ -2695,20 +2695,16 @@
    for (
-var 
 ii = 0, 
@@ -2828,16 +2828,18 @@
 '#text')
+ %7B
 %0A       
@@ -2851,17 +2851,12 @@
 entr
-ies.push(
+y = 
 desc
@@ -2870,17 +2870,16 @@
 odes%5Bii%5D
-)
 ;%0A      
@@ -2884,129 +2884,12 @@
     
-%7D%0A%0A
     
-    for (ii = 0, iLength = entries.length; ii %3C iLength; ii++) %7B%0A          var entry = entries%5Bii%5D;%0A          var 
 name
@@ -2917,24 +2917,26 @@
 owerCase();%0A
+  
           th
@@ -2977,24 +2977,36 @@
 ent.trim();%0A
+          %7D%0A
         %7D%0A  

Optimize metadata parsing