(function($) {

   /**
    * Platforms to check against the client one
    */
   var PLATFORMS = [
      {
         "key": "android",
         "value": navigator.userAgent,
         "search": "Android"
      },
      {
         "key": "ipod",
         "value": navigator.userAgent,
         "search": "(iPod;"
      },
      {
         "key": "iphone",
         "value": navigator.userAgent,
         "search": "(iPhone;"
      },
      {
         "key": "ipad",
         "value": navigator.userAgent,
         "search": "(iPad;"
      },
      {
         "key": "windows",
         "value": navigator.platform,
         "search": "Win"
      },
      {
         "key": "mac",
         "value": navigator.platform,
         "search": "Mac"
      },
      {
         "key": "linux",
         "value": navigator.platform,
         "search": "Linux"
      }
   ];

   /**
    * Large parts of this is stolen from swfobject.js v2
    */
   var client = (function() {
      var SHOCKWAVE_FLASH = "Shockwave Flash";
      var FLASH_MIME_TYPE = "application/x-shockwave-flash";
      var SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash";
      var result = {
         "platform": "unknown",
         "isFlashInstalled": false,
         "flashVersion": [0, 0, 0]
      };
      // determine the client platform
      for (var i=0; i<PLATFORMS.length; i+=1) {
         var props = PLATFORMS[i];
         if (props.value.toLowerCase().indexOf(props.search.toLowerCase()) > -1) {
            result.platform = props.key;
            break;
         }
      }
      // determine if and which version of flash is installed
      var desc = null;
      if (typeof(window.navigator.plugins != undefined) &&
            typeof(window.navigator.plugins[SHOCKWAVE_FLASH]) == "object") {
         desc = window.navigator.plugins[SHOCKWAVE_FLASH].description;
         // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates
         // whether plug-ins are enabled or disabled in Safari 3+
         if (desc && !(typeof(window.navigator.mimeTypes) != undefined &&
               window.navigator.mimeTypes[FLASH_MIME_TYPE] &&
               !window.navigator.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) {
            result.isIE = false;
            desc = desc.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
            result.flashVersion[0] = parseInt(desc.replace(/^(.*)\..*$/, "$1"), 10);
            result.flashVersion[1] = parseInt(desc.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
            result.flashVersion[2] = /[a-zA-Z]/.test(desc) ? parseInt(desc.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
         }
      } else if (typeof(window.ActiveXObject) != undefined) {
         try {
            var activeXObj = new ActiveXObject(SHOCKWAVE_FLASH_AX);
            // activeXObj will be null when ActiveX is disabled
            if (activeXObj && (desc = activeXObj.GetVariable("$version"))) {
               desc = desc.split(" ")[1].split(",");
               result.flashVersion = [parseInt(desc[0], 10), parseInt(desc[1], 10), parseInt(desc[2], 10)];
            }
         } catch(e) {
            // ignore
         }
      }
      result.isFlashInstalled = (result.flashVersion[0] > 0);
      return result;
   })();


   /**
    * @param {jQuery} $container The video player container
    * @param {Object} options The options
    * @constructor
    */
   var AvPlayer = function($container, options) {
      var self = this;
      var isHtml5 = false;
      var $player = null;

      /**
       * Initializes the video player
       */
      this.init = function() {
         var params = {
            "p": client.platform,
            "f": client.isFlashInstalled === true
         };
         if (options.type === AvPlayer.TYPE_VIDEO) {
            if ($.inArray(client.platform, ["iphone", "ipod", "android"]) > -1 ||
                     $("body").hasClass("mobile")) {
               params.q = AvPlayer.QUALITY_LOW;
            } else {
               params.q = AvPlayer.QUALITY_HIGH;
            }
         }
         $.ajax({
            "url": options.url + "?" + $.param(params),
            "cache": true,
            "dataType": "jsonp",
            "jsonpCallback": $container.attr("id"),
            "success": function(response, status, req) {
               self.render(response);
            },
            "error": function() {
               $("<div />").addClass("error").html("Dieses Element ist derzeit nicht verf&uuml;gbar.").appendTo($container);
            }
         });
      };

      /**
       * Renders the content passed as argument into the container represented
       * by this instance
       * @param {String} content The content to render
       */
      this.render = function(content) {
         $player = $(content).appendTo($container);
         isHtml5 = $player.is("audio,video");
         // android needs that
         if (options.type === AvPlayer.TYPE_VIDEO && client.platform === "android") {
            $player.bind("click.android", function() {
               this.play();
            });
         }

         // activate controls
         $(options.controls, $container).find("a").bind("click.player", function(event) {
            event.preventDefault();
            var $control = $(this);
            var method = $control.data("execute");
            if (typeof(method) === "string" && method.length > 0 && typeof(self[method]) === "function") {
               self[method]();
            }
         });
      };

      /**
       * Starts/Stops the player
       */
      this.togglePlay = function() {
         return this.executePlayerCommand("togglePlay");
      };

      /**
       * Mutes/unmutes the player
       */
      this.toggleMute = function() {
         return this.executePlayerCommand("toggleMute");
      };

      /**
       * Decreases the player volume
       */
      this.decreaseVolume = function() {
         return this.executePlayerCommand("decreaseVolume");
      };

      /**
       * Increases the player volume
       */
      this.increaseVolume = function() {
         return this.executePlayerCommand("increaseVolume");
      };

      /**
       * Stops the player and rewinds to the beginning of the video
       */
      this.stopRewind = function() {
         return this.executePlayerCommand("stopRewind");
      };

      /**
       * Executes a video player API command
       * @param command
       * @private
       */
      this.executePlayerCommand = function(command) {
         if (isHtml5 === true) {
            return AvPlayer.executeHtml5Command($player.get(0), command);
         }
         return AvPlayer.executeFlashCommand($player.get(0), command);
      };

      return this;
   };

   AvPlayer.TYPE_VIDEO = "video";
   AvPlayer.TYPE_AUDIO = "audio";
   AvPlayer.QUALITY_HIGH = 4;
   AvPlayer.QUALITY_LOW = 1;

   AvPlayer.executeFlashCommand = function(player, command) {
      if (player != null && typeof(player[command]) === "function") {
         try {
            player[command]();
         } catch (e) {
            // ignore
         }
      }
      return;
   };

   AvPlayer.executeHtml5Command = function(player, command) {
      if (player != null) {
         switch (command) {
            case "togglePlay":
               (player.paused) ? player.play() : player.pause();
               break;
            case "toggleMute":
               player.volume = (player.volume > 0) ? 0 : 0.8;
               break;
            case "decreaseVolume":
               player.volume = Math.max(player.volume - 0.1, 0);
               break;
            case "increaseVolume":
               player.volume = Math.min(player.volume + 0.1, 1);
               break;
            case "stopRewind":
               player.currentTime = 0;
               player.pause();
               break;
         }
      }
      return;
   };

   /**
    * Main plugin body
    */
   $.fn.avplayer = function(opts) {
      var options = $.extend({
         "controls": ".controls"
      }, opts);

      /**
       * Main plugin body
       */
      return this.each(function() {
         var $container = $(this);
         var player = new AvPlayer($container, options);
         $container.data("player", player);
         player.init();
      });
   };

})(jQuery);

