/*!
  {
  "name": "Flash",
  "property": "flash",
  "tags": ["flash"],
  "polyfills": ["shumway"]
  }
  !*/
/* DOC
Detects Flash support as well as Flash-blocking plugins
*/
define(['Modernizr', 'createElement', 'docElement', 'addTest', 'getBody', 'isSVG'], function(Modernizr, createElement, docElement, addTest, getBody, isSVG) {
  Modernizr.addAsyncTest(function() {

    var attachBody = function(body) {
      if (!docElement.contains(body)) {
        docElement.appendChild(body);
      }
    };
    var removeFakeBody = function(body) {
      // If we’re rockin’ an attached fake body, clean it up
      if (body.fake && body.parentNode) {
        body.parentNode.removeChild(body);
      }
    };
    var runTest = function(result, embed) {
      var bool = !!result;
      if (bool) {
        bool = new Boolean(bool);
        bool.blocked = (result === 'blocked');
      }
      addTest('flash', function() { return bool; });

      if (embed && body.contains(embed)) {

        // in case embed has been wrapped, as with ClickToPlugin
        while (embed.parentNode !== body) {
          embed = embed.parentNode;
        }

        body.removeChild(embed);
      }

    };
    var easy_detect;
    var activex;
    // we wrap activex in a try/catch because when Flash is disabled through
    // ActiveX controls, it throws an error.
    try {
      // Pan is an API that exists for Flash objects.
      activex = 'ActiveXObject' in window && 'Pan' in new window.ActiveXObject('ShockwaveFlash.ShockwaveFlash');
    } catch (e) {}

    easy_detect = !(('plugins' in navigator && 'Shockwave Flash' in navigator.plugins) || activex);

    if (easy_detect || isSVG) {
      runTest(false);
    }
    else {
      // Flash seems to be installed, but it might be blocked. We have to
      // actually create an element to see what happens to it.
      var embed = createElement('embed');
      var body = getBody();
      var blockedDetect;
      var inline_style;

      embed.type = 'application/x-shockwave-flash';

      // Need to do this in the body (fake or otherwise) otherwise IE8 complains
      body.appendChild(embed);

      // Pan doesn't exist in the embed if its IE (its on the ActiveXObject)
      // so this check is for all other browsers.
      if (!('Pan' in embed) && !activex) {
        attachBody(body);
        runTest('blocked', embed);
        removeFakeBody(body);
        return;
      }

      blockedDetect = function() {
        // if we used a fake body originally, we need to restart this test, since
        // we haven't been attached to the DOM, and therefore none of the blockers
        // have had time to work.
        attachBody(body);
        if (!docElement.contains(body)) {
          body = document.body || body;
          embed = createElement('embed');
          embed.type = 'application/x-shockwave-flash';
          body.appendChild(embed);
          return setTimeout(blockedDetect, 1000);
        }
        if (!docElement.contains(embed)) {
          runTest('blocked');
        }
        else {
          inline_style = embed.style.cssText;
          if (inline_style !== '') {
            // the style of the element has changed automatically. This is a
            // really poor heuristic, but for lower end Flash blocks, it the
            // only change they can make.
            runTest('blocked', embed);
          }
          else {
            runTest(true, embed);
          }
        }
        removeFakeBody(body);
      };

      // If we have got this far, there is still a chance a userland plugin
      // is blocking us (either changing the styles, or automatically removing
      // the element). Both of these require us to take a step back for a moment
      // to allow for them to get time of the thread, hence a setTimeout.
      //
      setTimeout(blockedDetect, 10);
    }
  });
});
