/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * 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.
 */

MODEL({
  package: 'foam.core.bootstrap',
  name: 'BrowserFileDAO',

  imports: [
    'document',
    'window'
  ],

  properties: [
    {
      name: 'pending',
      factory: function() { return {}; }
    },
    {
      name: 'preload',
      factory: function() { return {}; }
    },
    {
      name: 'rootPath',
      factory: function() {
        return this.window.FOAM_BOOT_DIR + '../js/';
      }
    },
    'looking_'
  ],

  methods: {
    toURL_: function(key) {
      return this.rootPath + key.replace(/\./g, '/') + '.js';
    },
    find: function(key, sink) {
      if ( this.preload[key] ) {
        sink && sink.put && sink.put(this.preload[key]);
        delete this.preload[key];
        return;
      }

      if ( this.pending[key] ) {
        this.pending[key].push(sink);
        return;
      }

      this.pending[key] = [sink];

      var tag = this.document.createElement('script');

      var onerror = function() {
        var pending = this.pending[key];
        delete this.pending[key];
        for ( var i = 0 ; i < pending.length ; i++ ) {
          pending[i] && pending[i].error && pending[i].error.apply(null, arguments);
        }
        tag.remove();
      }.bind(this);

      tag.callback = function() {
        this.looking_ = key;
        this.onData.apply(this, arguments);
        if ( this.looking_ ) {
          onerror();
        }
      }.bind(this);
      tag.src = this.toURL_(key);
      tag.onload = function() { tag.remove(); };
      tag.onerror = onerror;

      this.document.head.appendChild(tag);
    }
  },

  listeners: [
    {
      name: 'onData',
      code: function(data, latch) {
        var work = [anop];
        var obj = JSONUtil.mapToObj(this.X, data, undefined, work);

        if ( ! obj ) throw new Error('Failed to decode data: ' + data);

        if ( this.looking_ === obj.id ) this.looking_ = null;

        if ( ! this.pending[obj.id] ) {
          if ( latch ) {
            latch(data);
          } else {
            // Workaround for legacy apps that include extra models via
            // additional script tags.
            this.preload[obj.id] = obj;
          }
          return;
        }

        aseq.apply(null, work)(
          function(ret) {
            var sinks = this.pending[obj.id];
            delete this.pending[obj.id];
            if ( sinks ) {
              for ( var i = 0; i < sinks.length ; i++ ) {
                var sink = sinks[i];
                sink && sink.put && sink.put(obj);
              }
            }
          }.bind(this));
      }
    }
  ]
});

@@ -1533,16 +1533,41 @@
 cript');
+%0A      var looking = key;
 %0A%0A      
@@ -1885,399 +1885,8 @@
 ck =
- function() %7B%0A        this.looking_ = key;%0A        this.onData.apply(this, arguments);%0A        if ( this.looking_ ) %7B%0A          onerror();%0A        %7D%0A      %7D.bind(this);%0A      tag.src = this.toURL_(key);%0A      tag.onload = function() %7B tag.remove(); %7D;%0A      tag.onerror = onerror;%0A%0A      this.document.head.appendChild(tag);%0A    %7D%0A  %7D,%0A%0A  listeners: %5B%0A    %7B%0A      name: 'onData',%0A      code:
  fun
@@ -2088,29 +2088,23 @@
    if ( 
-this.
 looking
-_
  === obj
@@ -2113,21 +2113,15 @@
 d ) 
-this.
 looking
-_
  = n
@@ -2803,24 +2803,272 @@
 s));%0A      %7D
+.bind(this);%0A%0A      tag.onload = function() %7B%0A        if ( looking != null ) %7B%0A          onerror();%0A        %7D%0A        tag.remove();%0A      %7D;%0A      tag.onerror = onerror;%0A%0A      tag.src = this.toURL_(key);%0A%0A      this.document.head.appendChild(tag);
 %0A    %7D%0A  %5D%0A%7D
@@ -3064,14 +3064,14 @@
     %7D%0A  
-%5D
+%7D
 %0A%7D);%0A

Fix pong demo and any other class files that embed multiple classes in a single file.