const EventTarget = require('event-target-shim');
const Postmate = require('postmate/build/postmate.min');
Postmate.debug = true;

const initPosition = require('./initPosition');

class Player extends EventTarget {

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

    this.src = src;

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

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

    this.addEventListener('beforeunload', (event) => event.child.destroy());
  }

  start(model) {
    this._start();
    return new Postmate({
      container: document.body,
      url: this.src,
      model
    })
    .then(child => {
      this._start = () => this.dispatchBeforeUnloadEvent({child});
      this.restart = (modelUpdated) => this.start(Object.assign({}, model, modelUpdated));
      initPosition(child.frame);
      child.frame.style.position = 'absolute';
      child.get('size')
        .then(data => this.dispatchResizeEvent({data, child}));
      child.on('resize', (data) => this.dispatchResizeEvent({data, child}));

      this.dispatchLoadEvent({child});
      return child;
    });
  }
  _start() {}
  restart() {}

  dispatchResizeEvent({data, child}) {
    const event = new Event('resize');
    event.frame = child.frame;
    event.width = data.width;
    event.height = data.height;
    this.dispatchEvent(event);
  }

  dispatchBeforeUnloadEvent({child}) {
    const event = new Event('beforeunload');
    event.child = child;
    this.dispatchEvent(event);
  }

  dispatchLoadEvent({child}) {
    const event = new Event('load');
    event.child = child;
    this.dispatchEvent(event);
  }

  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;

@@ -276,352 +276,8 @@
 c;%0A%0A
-    var width = 300, height = 150;%0A    this.getContentSize = () =%3E (%7B width, height %7D);%0A    this.addEventListener('resize', () =%3E %7B%0A      width = event.data.width;%0A      height = event.data.height;%0A    %7D);%0A%0A    // cannot access port directly%0A    var port = null;%0A    this.setPort = (value) =%3E %7B%0A      port = this._setPort(value, port);%0A    %7D;%0A%0A
     
@@ -1499,1083 +1499,8 @@
  %7D%0A%0A
-  standBy(contentWindow) %7B%0A    return new Promise((resolve, reject) =%3E %7B%0A      addEventListener('message', function task(event) %7B%0A        if (event.source !== contentWindow) return;%0A        removeEventListener('message', task);%0A        resolve(event);%0A      %7D);%0A    %7D);%0A  %7D%0A%0A  connect(contentWindow) %7B%0A    return new Promise((resolve, reject) =%3E %7B%0A%0A      // TODO: Request to reload if connected%0A%0A      this.standBy(contentWindow)%0A      .then((event) =%3E %7B%0A        this.setPort(event.ports%5B0%5D);%0A        resolve();%0A      %7D);%0A    %7D);%0A  %7D%0A%0A  postMessage() %7B%0A    throw new Error('Missing a port. It has not connected yet.');%0A  %7D%0A%0A  _setPort(next, current) %7B%0A    if (current) %7B%0A      current.onmessage = null;%0A    %7D%0A    next.onmessage = (event) =%3E %7B%0A      this.dispatchEvent(event);%0A      if (event.data.method) %7B%0A        const partialEvent = new Event(event.data.method + '.message');%0A        partialEvent.data = event.data;%0A        this.dispatchEvent(partialEvent);%0A      %7D%0A    %7D;%0A    this.postMessage = (...args) =%3E %7B%0A      next.postMessage(...args);%0A    %7D;%0A    return next;%0A  %7D%0A
 %7D%0A%0Am

remove old