/*******************************************************************************
 * Copyright (c) 2009, 2012 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    IBM Corporation - initial API and implementation
 *******************************************************************************/ 
//
// Ad-hoc codes to bridge the gap in implementations between modern browsers and old IEs
//
(function () {
  var FORMAT_REPLACE = { ogv: 'wmv', oga: 'wma', mp4: 'wmv', m4a: 'wma' }; // for new Audio(src) and HTMLMediaElement#src (not for HTMLSourceElement#src)
  var TYPE_SUPPORTED = { 'video/x-ms-wmv': true, 'audio/x-ms-wma': true, 'video/mpeg': true, 'audio/mpeg': true }; // for HTMLSourceElement#type
  var MAX_PRELOADERS = 4;

  if (typeof XMLHttpRequest == 'undefined') {
    XMLHttpRequest = function () {
      return new ActiveXObject('MSXML2.XMLHTTP');
    };
  }

  globalEventListeners = {};

  var fixMediaElement = function (media) {
    var wmpMedia = createWMPMedia(media);
    media.appendChild(wmpMedia);
    media.__wmpMedia__ = wmpMedia;
    media.__eventListeners__ = {};
    media.addEventListener = addEventListener;
    media.dispatchEvent = dispatchEvent;
    media.play = play;
    media.pause = pause;
    media.paused = true;
    media.ended = false;
    media.volume = wmpMedia.settings.volume / 100;
    media.currentTime = media.__prevTime__ = wmpMedia.controls.currentPosition;

    createScript(wmpMedia.id, 'positionChange(oldPosition, newPosition)', 'globalEventListeners["' + wmpMedia.id + '"].positionChange(oldPosition, newPosition)');
    createScript(wmpMedia.id, 'playStateChange(NewState)', 'globalEventListeners["' + wmpMedia.id + '"].playStateChange(NewState)');

    globalEventListeners[wmpMedia.id] = {
      positionChange: function (oldPosition, newPosition) {
        media.dispatchEvent({ type: 'seeked', target: media });
      },
      
      playStateChange: function (NewState) {
        switch (NewState) {
        case 2: // Paused
          media.paused = true;
          media.ended = false;
//        media.dispatchEvent({ type: 'pause', target: media });
          break;
        case 3: // Playing
          media.paused = false;
          media.ended = false;
          media.dispatchEvent({ type: 'playing', target: media });
          break;
        case 8: // MediaEnded
          media.paused = true;
          media.ended = true;
          media.dispatchEvent({ type: 'ended', target: media });
          break;
        case 6: case 7: // Buffering, Waiting
          media.dispatchEvent({ type: 'waiting', target: media });
          break;
        }
      }
    };

    if (media.getAttribute('preload') != 'none' && !media.__wmpMedia__.settings.autoStart) {
      preloadMedia(media);
    }

    media.addEventListener('seeked', function (e) {
      var media = e.target;

      if (media.ended) {
        media.__pausedForSync__ = true;
        media.ended = false;
      }
    }, false);
    
    var prevTime = wmpMedia.controls.currentPosition;

    setInterval(function () {
      var time = wmpMedia.controls.currentPosition;

      if (time != prevTime) {
        media.dispatchEvent({ type: 'timeupdate', target: media });
      }
      else {
        media.dispatchEvent({ type: '__noop__', target: media });
      }

      prevTime = time;
    }, 250);
  };

  var createScript = function (htmlFor, event, text) {
    var s = document.createElement('script');
    s.htmlFor = htmlFor;
    s.event = event;
    s.text = text;
    document.body.appendChild(s);
  };

  var addEventListener = function (type, handler, capture) {
    var v = this.__eventListeners__[type] || [];
    v.push(handler);
    this.__eventListeners__[type] = v;
  };

  var dispatchEvent = function (e) {
    setTimeout(function () {
      var media = e.target;

      if (media.currentTime != media.__prevTime__) {
        media.__wmpMedia__.controls.currentPosition = media.__prevTime__ = media.currentTime;
      }

      media.__prevTime__ = media.currentTime = media.__wmpMedia__.controls.currentPosition;
      media.__wmpMedia__.settings.volume = media.volume * 100;
      media.volume = media.__wmpMedia__.settings.volume / 100;
      var v = media.__eventListeners__[e.type] || [];

      for (var i = 0; i < v.length; ++i) {
        v[i].call(media, e);
      }
    }, 0);
  };

  var play = function () {
    this.__wmpMedia__.controls.currentPosition = this.currentTime;
    this.__wmpMedia__.controls.play();
    this.paused = false;
    this.dispatchEvent({ type: 'play', target: this });
  };

  var pause = function () {
    this.currentTime = this.__wmpMedia__.controls.currentPosition;
    this.__wmpMedia__.controls.pause();
    this.paused = true;
    this.dispatchEvent({ type: 'pause', target: this });
  };

  var preloaders = 0;

  var preloadMedia = function (media) {
    (function () {
      if (preloaders < MAX_PRELOADERS) {
        var wmpFetch = createWMPFetch(media);
        media.appendChild(wmpFetch);
        ++preloaders;
        
        createScript(wmpFetch.id, 'openStateChange(NewState)', 'globalEventListeners["' + wmpFetch.id + '"].openStateChange(NewState)');
        createScript(wmpFetch.id, 'playStateChange(NewState)', 'globalEventListeners["' + wmpFetch.id + '"].playStateChange(NewState)');
        
        globalEventListeners[wmpFetch.id] = {
          openStateChange: function (NewState) {
            if (NewState == 13) { // MediaOpen
              --preloaders;
            }
          },
          
          playStateChange: function (NewState) {
            if (NewState == 3) { // Playing
              wmpFetch.controls.stop();
            }
          }
        };
      }
      else {
        setTimeout(arguments.callee, 1000);
      }
    })();
  };

  var fixDOMStructure = function (media) {
    var newMedia = document.createElement(media.outerHTML);
    var v = [];

    for (var e = media.nextSibling; e.tagName != '/' + media.tagName; e = e.nextSibling) {
      v.push(e);
    }

    for (var i = 0; i < v.length; ++i) {
      newMedia.appendChild(v[i]);
    }

    media.parentNode.replaceChild(newMedia, media);

    return newMedia;
  };

  var createWMPMedia = function (media) {
    var wmp = document.createElement('object');
    wmp.appendChild(createWMPParam('URL', getSourceURL(media)));
    wmp.appendChild(createWMPParam('autoStart', media.getAttribute('autoplay') !== null ? 'true' : 'false'));
    wmp.appendChild(createWMPParam('uiMode', media.getAttribute('controls') !== null ? 'full' : 'none'));
    wmp.appendChild(createWMPParam('mute', media.getAttribute('muted') !== null ? 'true' : 'false'));
    wmp.appendChild(createWMPParam('shrinkToFit', 'true'));
    wmp.appendChild(createWMPParam('stretchToFit', 'true'));
    wmp.appendChild(createWMPParam('windowlessVideo', 'true'));
    wmp.width = media.getAttribute('width') || 1;
    wmp.height = media.getAttribute('height') || 1;
    wmp.id = document.uniqueID;
    wmp.classid = 'CLSID:6BF52A52-394A-11D3-B153-00C04F79FAA6';
    wmp.settings.mute = media.getAttribute('muted') !== null; // <param name=mute> does not work (?)
    return wmp;
  };

  var createWMPFetch = function (media) {
    var wmp = document.createElement('object');
    wmp.appendChild(createWMPParam('URL', getSourceURL(media)));
    wmp.width = 1;
    wmp.height = 1;
    wmp.id = document.uniqueID;
    wmp.className = 'vd-prefetcher';
    wmp.classid = 'CLSID:6BF52A52-394A-11D3-B153-00C04F79FAA6';
    wmp.settings.mute = true;
    return wmp;
  };
  
  var createWMPParam = function (name, value) {
    var p = document.createElement('param');
    p.name = name;
    p.value = value;
    return p;
  };

  var getSourceURL = function (media) {
    if (media.src) {
      return media.src.replace(/\b\w+$/, function (e) {
        return FORMAT_REPLACE[e] || e;
      });
    }

    var v = media.getElementsByTagName('source');

    for (var i = 0; i < v.length; ++i) {
      if (TYPE_SUPPORTED[v[i].type]) {
        return v[i].src;
      }
    }

    return v[0].src;
  };
  
  if (typeof Audio == 'undefined') {
    Audio = function (url) {
      this.src = url;
      fixMediaElement(this);
    };

    Audio.prototype.appendChild = function (e) { document.body.appendChild(e) };
    Audio.prototype.getAttribute = function (_) { return null };
  }

  var videoElems = document.getElementsByTagName('video');

  for (var i = 0; i < videoElems.length; ++i) {
    fixMediaElement(fixDOMStructure(videoElems[i]));
  }
  
  var audioElems = document.getElementsByTagName('audio');

  for (var i = 0; i < audioElems.length; ++i) {
    fixMediaElement(fixDOMStructure(audioElems[i]));
  }
})();

