/**
 * SWFの表示を管理するクラス
 *
 *
 */
if (JpQamobSWFManager === undefined) {

  var JpQamobSWFManager = (function() {
    // SWFManagerのインスタンス
    var _instance = null;

    // Flashのサイズ
    var _screen = {'small':[170, 280], 'large':[400, 300], 'extra':[745, 540]};

    // デフォルトのドメイン
    var _defaultDomain = 'qamob.jp/';

    // シャドーレイヤーのID
    var _shadowId = 'jpqamobextrashadowlayer';

    // テンプレート(特大)用のID
    var _containerId = 'jpqamobextratemplatecontainer';

    /**
     * ローカルコンストラクタ
     */
    function SWFManagerInstance() {
      this._params = {};
      this._key = null;
    }

    /**
     * swfファイルを出力するタグを埋め込みます。
     * このメソッドは原則としてサーバ側のJSONPレスポンスからコールバックすることを想定しています。
     *
     */
    SWFManagerInstance.prototype.callbackShow = function(args){

      // インスタンスユニークkeyをローカルに復元
      var key = this._key;

      // argsを元にthis._param()の洗い替え
      if (args.swfFileNameSmallDisplay && args.swfFileNameSmallDisplay != null && this._params[key]['smallTemplate']) {
          this._params[key]['smallTemplate'] = args.swfFileNameSmallDisplay;
      }
      if (args.swfFileNameLargeDisplay && args.swfFileNameLargeDisplay != null && this._params[key]['largeTemplate']) {
          this._params[key]['largeTemplate'] = args.swfFileNameLargeDisplay;
      }
      if (args.swfFileNameDisplay && args.swfFileNameDisplay != null && this._params[key]['extraTemplate']) {
          this._params[key]['extraTemplate'] = args.swfFileNameDisplay;
      }
      if (this._params[key]['smallTemplate']) {
          if (args.swfFileSmallHeight && args.swfFileSmallHeight != null) {
              this._params[key]['height'] = args.swfFileSmallHeight;
          }
          if (args.swfFileSmallWidth && args.swfFileSmallWidth != null) {
              this._params[key]['width'] = args.swfFileSmallWidth;
          }
      } else {
          if (args.swfFileLargeHeight && args.swfFileLargeHeight != null) {
              this._params[key]['height'] = args.swfFileLargeHeight;
          }
          if (args.swfFileLargeWidth && args.swfFileLargeWidth != null) {
              this._params[key]['width'] = args.swfFileLargeWidth;
          }
      }

      // テンプレート(小)または(大)用のパラメータを構築
      if (this._params[key]['smallTemplate'] || this._params[key]['largeTemplate']) {
          var temp = DomUtil.copy(this._params[key]);
          temp['key'] = key;
      	  if (this._params[key]['width']) {
	        temp['width'] = this._params[key]['width'];
		  } else {
	        temp['width'] = (this._params[key]['smallTemplate']) ? _screen['small'][0] : _screen['large'][0];
		  }
		  if (this._params[key]['height']) {
	        temp['height'] = this._params[key]['height'];
		  } else {
	        temp['height'] = (this._params[key]['smallTemplate']) ? _screen['small'][1] : _screen['large'][1];
		  }
          temp['templateName'] = (this._params[key]['smallTemplate']) ? this._params[key]['smallTemplate'] : this._params[key]['largeTemplate'];
          temp['blogParts'] = getScriptTags(this._params[key]);

          // Flashを表示
          document.write(getSWFObjectTag(temp));
      }
    };

    /**
     * Flashテンプレート(小)または(大)が指定された場合は実行します。
     * @param 問題の最後に表示するURL (String)
     * @param パラメータ群 (Object)
     */
    SWFManagerInstance.prototype.show = function(url, params){
      if (!params) return;

      // 引数のパラメータをインスタンスフィールドにコピー
      var key = 'q' + Math.random();
      // コールバック関数から呼び出すためにkeyをインスタンスフィールドに保持する
      this._key = key;
      this._params[key] = {};
      DomUtil.copy(params, this._params[key]);

      // url毎のdomain設定処理
      if (url != null && url != '' && url.search(/^https?:\/\//) != -1) this._params[key]['endingUrl'] = url;
      if (this._params[key]['domain'] && this._params[key]['domain'].search(/\/$/) == -1) {
          this._params[key]['domain'] = this._params[key]['domain'] + '/';
      }

      // collbackを呼び出すscriptタグを生成
      document.write("<script type='text/javascript' src='http://"
                      + params['domain']
                      + "swfManagerCallback.html?"
                      + "lectureId="+ ((params['lectureId']) ? params['lectureId'] : null)
                      + "&lecturePath=" + params['lecturePath']
                      + " '></script>");
    };

    /**
     * Flashテンプレート(特大)を実行します。
     */
    SWFManagerInstance.prototype.execute = function(key) {
      if (!this._params[key] || !this._params[key]['extraTemplate']) return;

      // Flash表示用のコンテナを作成
      var container = getExtraTemplateContainer(_containerId, _screen['extra'][0], _screen['extra'][1]);

      // シャドー・レイヤーを作成
      showShadowLayer(_shadowId, container);

      // パラメータを構築
      var temp = DomUtil.copy(this._params[key]);
      temp['width'] = _screen['extra'][0];
      temp['height'] = _screen['extra'][1];
      temp['templateName'] = this._params[key]['extraTemplate'];
      temp['callerType'] = (this._params[key]['smallTemplate']) ? 'small' : 'large';

      // Flashを表示
      container.innerHTML = getSWFObjectTag(temp);
    };

    /**
     * Flashテンプレート(特大)の実行を中止します。
     */
    SWFManagerInstance.prototype.suspend = function() {
      containerErase();
    };

    // -----------------------------------------------------------------
    // ドキュメント・オブジェクトを操作するユーティリティ
    // -----------------------------------------------------------------
    var DomUtil = {};

    /**
     * ウインドウサイズを取得します。
     */
    DomUtil.getWindowSize = function() {
      var result = {};
      if (document.documentElement && document.documentElement.clientWidth) {
        result.width = document.documentElement.clientWidth;
        result.height = (window.innerHeight) ? window.innerHeight : document.documentElement.clientHeight;
      } else {
        result.width = document.body.clientWidth;
        result.height = (window.innerHeight) ? window.innerHeight : document.body.clientHeight;
      }
      return result;
    };

    /**
     * スクロール量を取得します。
     */
    DomUtil.getScrollSize = function() {
      var result = {};
      if (document.documentElement.scrollTop) {
        result.top = document.documentElement.scrollTop;
      } else {
        result.top = document.body.scrollTop;
      }
      if (document.documentElement.scrollLeft) {
        result.left = document.documentElement.scrollLeft;
      } else {
        result.left = document.body.scrollLeft;
      }
      return result;
    };

    /**
     * イベントを登録します。
     * @param target イベントを登録される要素
     * @param type イベントの種類
     * @param func 登録されるコールバック関数
     * @return 成功した場合 true、失敗した場合 false
     */
    DomUtil.addEventListener =  function(target, type, func) {
      if (!target) return false;
      if (target.addEventListener) {
        target.addEventListener(type, func, false);
      } else if (target.attachEvent) {
        target.attachEvent('on' + type, func);
      } else {
        return false;
      }
      return true;
    };

    /**
     * イベントを削除します。
     * @param target イベントを削除される要素
     * @param type イベントの種類
     * @param func 削除されるコールバック関数
     * @return 成功した場合 true、失敗した場合 false
     */
    DomUtil.removeEventListener = function(target, type, func) {
      if (!target) return false;
      if (target.removeEventListener) {
        target.removeEventListener(type, func, false);
      } else if(target.detachEvent) {
        target.detachEvent('on' + type, func);
      } else {
        return false;
      }
      return true;
    };

    /**
     * オブジェクトの要素をコピーします。
     * コピー先のオブジェクトが指定されない場合は、オブジェクトを生成します。
     * @param コピー元
     * @param コピー先
     * @return コピー先のオブジェクト
     */
    DomUtil.copy = function(src, dest) {
      var result = (!dest) ? {} : dest;
      for (var key in src) {
        result[key] = src[key];
      }
      return result;
    };

    /**
     * ウインドウサイズが変更された場合、スクロール発生時に
     * シャドー・レイヤーおよびコンテナを再配置するイベントリスナー
     */
    var containerResize = function() {
      var shadow = document.getElementById(_shadowId);
      var container = document.getElementById(_containerId);

      var winSize = DomUtil.getWindowSize();
      var scrollSize = DomUtil.getScrollSize();

      container.style.top = parseInt((winSize.height - container.offsetHeight) / 2 + scrollSize.top) + 'px';
      container.style.left = parseInt((winSize.width - container.offsetWidth) / 2 + scrollSize.left) + 'px';

      shadow.style.top = scrollSize.top + 'px';
      shadow.style.left = scrollSize.left + 'px';
      shadow.style.width = winSize.width + 'px';
      shadow.style.height = winSize.height + 'px';
    };

    /**
     * コンテナを消去します。
     */
    var containerErase = function() {
      hideShadowLayer(_shadowId);
      hideExtraTemplateContainer(_containerId);
    };


    // -----------------------------------------------------------------
    // テンプレート(特大)を表示するための処理
    // -----------------------------------------------------------------
    /**
     * シャドー・レイヤーを表示します。
     * @param シャドー・レイヤーを特定するID
     * @param シャドー・レイヤーに表示する要素
     */
    function showShadowLayer(shadowId, container) {
      // レイヤーを追加
      var shadow = document.getElementById(shadowId);
      if (shadow) {
        document.body.removeChild(shadow);
      }
      shadow = document.createElement('div');
      shadow.id = shadowId;
      document.body.appendChild(shadow);

      var scrollSize = DomUtil.getScrollSize();
      shadow.style.position = 'absolute';
      shadow.style.left = scrollSize.left + 'px';
      shadow.style.top = scrollSize.top + 'px';
      shadow.style.zIndex = 90000;

      // レイヤーをフェードイン
      var winSize = DomUtil.getWindowSize();
      var opacity = 0.0;
      var timer = setInterval(function() {
        if (opacity <= 8.5) {
          shadow.style.width = winSize.width + 'px';
          shadow.style.height = winSize.height + 'px';
          shadow.style.backgroundColor = '#000000';
          shadow.style.filter = 'alpha(opacity=' + (opacity * 10) + ')';
          shadow.style.MozOpacity = opacity / 10;
          shadow.style.opacity = opacity / 10;
          opacity = opacity + 1;
        } else {
          // タイマーをクリア
          clearInterval(timer);

          // 表示用コンテナを表示
          container.style.zIndex = 90001;
          document.body.appendChild(container);

          // ウインドウリサイズ対応
          containerResize();
          DomUtil.addEventListener(window, 'resize', containerResize);
          DomUtil.addEventListener(window, 'scroll', containerResize);
        }
      }, 2);
    };

    /**
     * テンプレート(特大)を表示するコンテナを生成します。
     * @param コンテナを特定するID
     * @param 幅
     * @param 高さ
     * @return テンプレート(特大)表示用要素
     */
    function getExtraTemplateContainer(containerId, width, height) {

      var container = document.getElementById(containerId);
      if (container) {
        container.parentNode.removeChild(container);
      }
      container = document.createElement('div');
      container.id = containerId;

      container.style.position = 'absolute';
      container.style.width = width + 'px';
      container.style.height = height + 'px';

      return container;
    };

    /**
     * フラッシュを表示するタグを生成します。
     * @param パラメータ群
     */
    function getSWFObjectTag(params) {
      // テンプレートファイルのURLを生成
      var templateURL = 'http://' + params['domain'] + 'swf/' + params['templateName'] + '.swf?' + new Date().getTime();

      // ドメイン
      var domain = (params['domain']) ? params['domain'] : _defaultDomain;

      // Flashへ渡すパラメータを構築
      var flashVars = [];
      if (params['lectureId']) {
        flashVars.push('lectureId=' + params['lectureId']);
      } else if (params['lecturePath']) {
        flashVars.push('lecturePath=' + params['lecturePath']);
      }

      var encordedAmp = encodeURIComponent('&');
      if (params['endingUrl']) flashVars.push('endingUrl=' + params['endingUrl'].replace(/&/g, encordedAmp));
      if (params['preview']) flashVars.push('preview=' + params['preview']);
      var encordedDoubleQuot = encodeURIComponent('"');
      if (params['blogParts']) flashVars.push('blogParts=' + params['blogParts'].replace(/\"/g, encordedDoubleQuot));
      if (params['key']) flashVars.push('token=' + params['key']);
      if (params['callerType']) flashVars.push('callerType=' + params['callerType']);
      flashVars.push('domain=' + domain);

      // タグを構築
      var result = [];
      result.push('<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="');
      result.push(params['width']);
      result.push('" height="');
      result.push(params['height']);
      result.push('" id="external_');
      result.push(params['templateName']);
      result.push('" align="middle">');
      result.push('<param name="allowScriptAccess" value="always" />');
      result.push('<param name="quality" value="high" />');
      result.push('<param name="wmode" value="transparent" />');
      result.push('<param name="flashVars" value="');
      result.push(flashVars.join('&'));
      result.push('" /><param name="movie" value="');
      result.push(templateURL);
      result.push('" />');
      result.push('<embed src="');
      result.push(templateURL);
      result.push('" flashVars="');
      result.push(flashVars.join('&'));
      result.push('" quality="high" width="');
      result.push(params['width']);
      result.push('" height="');
      result.push(params['height']);
      result.push('" name="external_');
      result.push(params['templateName']);
      result.push('" wmode="transparent" align="middle" allowScriptAccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" /></object>');

      return result.join('');
    };

    /**
     * ブログパーツを表示するためのスクリプトを生成します。
     * @param 入力パラメータ群
     */
    function getScriptTags(params) {
      var result = [];
      result.push('&lt;script type="text/javascript" src="http://');
      result.push((params['domain']) ? params['domain'] : _defaultDomain);
      result.push('js/swf_manager.js"&gt;&lt;/script&gt;');
      result.push('&lt;script type="text/javascript"&gt;JpQamobSWFManager.instance.show("", {');
      var options = [];
      for (var key in params) {
        if (key != 'endingUrl' && key != 'preview') {
          options.push(key + ':"' + params[key] + '"')
        }
      }
      result.push(options.join(','));
      result.push('});&lt;/script&gt;');

      return result.join('');
    };

    /**
     * シャドー・レイヤーを消去します。
     * @param シャドー・レイヤーを特定するID
     */
    function hideShadowLayer(shadowId) {
      var shadow = document.getElementById(shadowId);
      if (!shadow) return;

      // レイヤーをフェードアウト
      var opacity = 8.5;
      var timer = setInterval(function() {
        if (opacity >= 0) {
          shadow.style.backgroundColor = '#000000';
          shadow.style.filter = 'alpha(opacity=' + (opacity * 10) + ')';
          shadow.style.MozOpacity = opacity / 10;
          shadow.style.opacity = opacity / 10;
          opacity = opacity - 1;
        } else {
          /* インターバル設定を解除して、レイヤーを削除 */
          clearInterval(timer);
          document.body.removeChild(shadow);
          DomUtil.removeEventListener(window, 'resize', containerResize);
          DomUtil.removeEventListener(window, 'scroll', containerResize);
        }
      }, 2);
    };

    /**
     * テンプレート(特大)を表示するコンテナを削除します。
     * @param コンテナを特定するID
     */
    function hideExtraTemplateContainer(containerId) {
      document.body.removeChild(document.getElementById(containerId));
    }


    return new function() {
      if (_instance == null) {
        _instance = new SWFManagerInstance();
        _instance.constructor = null;
      }
      this.instance = _instance;
    }
  })();
}
