const EventTarget = require('event-target-shim');

class Player extends EventTarget {

  constructor({src, contentWindow} = {}) {
    super();

    this.src = src;
    this.contentWindow = contentWindow;

    var width = 300, height = 150;
    this.getContentSize = () => ({ width, height });
    this.addEventListener('resize.message', () => {
      width = event.data.width;
      height = event.data.height;
    });

    // cannot access port directly
    var port = null;
    this.setPort = (value) => {
      port = this._setPort(value, port);
    };
  }

  start({dependencies = [], code = ''}) {
    this.contentWindow.location.assign(this.src);
    this.lastLoaded = { dependencies, code };
    return this
      .connect(this.contentWindow)
      .then(() => {
        this.postMessage({
          method: 'require',
          dependencies,
          code,
        });
        return this;
      });
  }

  restart() {
    if (!this.lastLoaded) return;
    return this.start(this.lastLoaded);
  }

  standBy(contentWindow) {
    return new Promise((resolve, reject) => {
      addEventListener('message', function task(event) {
        if (event.source !== contentWindow) return;
        removeEventListener('message', task);
        resolve(event);
      });
    });
  }

  connect(contentWindow) {
    return new Promise((resolve, reject) => {

      // TODO: Request to reload if connected

      this.standBy(contentWindow)
      .then((event) => {
        this.setPort(event.ports[0]);
        resolve();
      });
    });
  }

  postMessage() {
    throw new Error('Missing a port. It has not connected yet.');
  }

  _setPort(next, current) {
    if (current) {
      current.onmessage = null;
    }
    next.onmessage = (event) => {
      this.dispatchEvent(event);
      if (event.data.method) {
        const partialEvent = new Event(event.data.method + '.message');
        partialEvent.data = event.data;
        this.dispatchEvent(partialEvent);
      }
    };
    this.postMessage = (...args) => {
      next.postMessage(...args);
    };
    return next;
  }
}

module.exports = Player;

@@ -42,16 +42,145 @@
 -shim');
+%0Aconst Postmate = require('postmate/build/postmate.min');%0APostmate.debug = true;%0A%0Aconst initPosition = require('./initPosition');
 %0A%0Aclass 
@@ -231,23 +231,8 @@
 %7Bsrc
-, contentWindow
 %7D = 
@@ -274,48 +274,8 @@
 src;
-%0A    this.contentWindow = contentWindow;
 %0A%0A  
@@ -393,24 +393,16 @@
 ('resize
-.message
 ', () =%3E
@@ -632,89 +632,93 @@
 art(
-%7Bdependencies = %5B%5D, code = ''%7D) %7B%0A    this.contentWindow.location.assign(
+file) %7B%0A    return new Postmate(%7B%0A      container: document.body,%0A      url: 
 this.src
 );%0A 
@@ -717,238 +717,393 @@
 .src
-);
+,
 %0A    
-this.lastLoaded = %7B dependencies, code %7D;
+  model: %7Bfile%7D%0A    %7D)
 %0A    
-return this%0A      .connect(this.contentWindow)%0A      .then(() =%3E %7B%0A        this.postMessage(%7B%0A          method: 'require',%0A          dependencies,%0A          code,%0A        %7D);%0A  
+.then(child =%3E %7B%0A      this.restart = () =%3E %7B%0A        child.destroy();%0A        this.start(file);%0A      %7D;%0A      initPosition(child.frame);%0A      child.frame.style.position = 'absolute';%0A      child.get('size')%0A        .then(data =%3E this.dispatchResizeEvent(%7Bdata, child%7D));%0A      child.on('resize', (data) =%3E this.dispatchResizeEvent(%7Bdata, child%7D));%0A%0A
     
@@ -1115,16 +1115,15 @@
 urn 
-this;%0A  
+child;%0A
     
@@ -1137,91 +1137,205 @@
 %0A%0A  
-restart() %7B%0A    if (!this.lastLoaded) return;%0A    return this.start(this.lastLoaded
+dispatchResizeEvent(%7Bdata, child%7D) %7B%0A    const event = new Event('resize');%0A    event.frame = child.frame;%0A    event.width = data.width;%0A    event.height = data.height;%0A    this.dispatchEvent(event
 );%0A 

migrate to postmate