/**
 * FlashElement.jsクラス
 * フラッシュを外部読み込みするための関数
 *
 * @return
 * @type    Function
 * @class
 */
var  FlashElement = function(){

	    // thisをthatへ
		var that = this;

	    // プロパティの初期化---------------
	    // object要素の属性
	    var aAttributes                = [];
	    // param要素の情報
	    var aParams                    = [];
	    // プロトコル指定
	    var sProtocol                  = 'http';
	    // 構成されたHTML
	    var sFlashHTML                 = '';
	    // 構成されたobject要素のHTML (ただし閉じてない)
	    var sObjectHTML                = '';
	    // 構成されたparam要素のHTML
	    var sParamHTML                 = '';
	    // 構成されたembed要素のHTML
	    var sEmbedHTML                 = '';
	    
	    // 定数定義
		// Flashがインストールされていない場合のダウンロード先 (プロトコル指定なし)
		var FLASH_DEFAULT_CLASSID       = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
		var FLASH_DEFAULT_DL_URL_OBJECT = 'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0';
		var FLASH_DEFAULT_DL_URL_EMBED  = 'www.macromedia.com/go/getflashplayer';
		var FLASH_DEFAULT_MIME_TYPE     = 'application/x-shockwave-flash';
		var FLASH_DEFAULT_DECLARE       = false;
		var FLASH_DEFAULT_SWLIVECONNECT = 'true';
		var FLASH_DEFAULT_QUALITY       = 'high';
		var FLASH_DEFAULT_LOOP          = 'true';
		var FLASH_DEFAULT_WMODE         = 'window';
		var FLASH_DEFAULT_PLAY          = 'true';
		var FLASH_DEFAULT_MENU          = 'true';
		var FLASH_DEFAULT_SCALE         = 'exhactfit';
		var FLASH_DEFAULT_SALIGN        = 'c';

	/**
     * nFlashElementMake
     * Flashを出力するためのobject要素/embed要素 を生成する関数
     *
     * @return
     * @type    Function
     * @class   FlashElement
     */
	var nFlashElementMake = function(aFlashOptions, blSSL){

	    // SSL接続をするか否か？
	    if ( blSSL==true ){
	        sProtocol = 'https';
	    }

	    // オプション情報のパース
	    nFlashElementParseInfo(aFlashOptions);

	    // 各要素を生成
	    nFlashElementMakeObject();
	    nFlashElementMakeParam();
	    nFlashElementMakeEmbed();
	    // object要素とparam要素とembed要素を合わせる
	    nFlashElementCombine();

	    return ;
	};

	/**
     * nSetElement
     * Flashを出力するためのobject要素/embed要素 を生成する関数
     *
     * @return
     * @type    Function
     * @class   FlashElement
     */
	var nSetElement = function(){
	    aAttributes['classid']       = FLASH_DEFAULT_CLASSID;
	    aAttributes['codebase']      = sProtocol+'://'+FLASH_DEFAULT_DL_URL_OBJECT;
	    aAttributes['pluginspage']   = sProtocol+'://'+FLASH_DEFAULT_DL_URL_EMBED;
	    aAttributes['type']          = FLASH_DEFAULT_MIME_TYPE;
	    aAttributes['declare']       = FLASH_DEFAULT_DECLARE;
	    aAttributes['swliveconnect'] = FLASH_DEFAULT_SWLIVECONNECT;
	    aParams['quality']           = FLASH_DEFAULT_QUALITY;
	    aParams['loop']              = FLASH_DEFAULT_LOOP;
	    aParams['wmode']             = FLASH_DEFAULT_WMODE;
	    aParams['play']              = FLASH_DEFAULT_PLAY;
	    aParams['menu']              = FLASH_DEFAULT_MENU;
	    aParams['scale']             = FLASH_DEFAULT_SCALE;
	    aParams['salign']            = FLASH_DEFAULT_SALIGN;
	    return ;
	};


	/**
     * nFlashElementParseInfo
     * object要素/embed要素 のオプションをパースする関数
     *
     * @return
     * @type    Function
     * @class   FlashElement
     */
	var nFlashElementParseInfo = function(aFlashOptions){

	    // パースする配列は存在するかチェック
	    if ( ! aFlashOptions ){
	        return;
	    }

	    // 配列の要素が存在するかチェック
	    var len = iFlashElementCountArray(aFlashOptions);
	    if ( len<1 ){
	        return;
	    }
	    
	    // データをセット
	    nSetElement();

	    // 配列の要素が存在する → objectか配列 → 繰り返し
	    for ( var sIndex in aFlashOptions ){
	        var sIndexLowerCase = sIndex.toLowerCase();
	        switch (sIndexLowerCase){
	            // object要素の属性値セット(W3C)
	            case 'class': case 'id': case 'title':
	            case 'style':
	            case 'archive': case 'classid': case 'codebase': case 'codetype': case 'data': case 'declare':
	            case 'height': case 'name': case 'standby': case 'tabindex': case 'type': case 'width':
	            case 'onload':
	            // W3Cの定義外
	            case 'hspace': case 'vspace': case 'align':
	            case 'pluginspage': case 'swliveconnect':
	                aAttributes[sIndexLowerCase] = aFlashOptions[sIndex];
	                break;

	            // param要素への属性値セット
	            case 'movie': case 'quality': case 'loop': case 'bgcolor': case 'wmode':
	            case 'play': case 'menu': case 'scale': case 'salign':
	                aParams[sIndex] = aFlashOptions[sIndex];
	                break;

	            // その他は param要素の属性ということにする
	            default:
	                aParams[sIndex] = aFlashOptions[sIndex];
	                break;
	        }
	    }
	    return;
	};

	/**
     * nFlashElementMakeObject
     * object要素生成する関数
     *
     * @return
     * @type    Function
     * @class   FlashElement
     */
	var nFlashElementMakeObject = function(){
	    
	    // 生成するHTMLの初期化
	    sObjectHTML = '';

	    // パースする配列は存在するかチェック
	    if ( ! aAttributes ){
	        return;
	    }

	    // 配列の要素が存在するかチェック
	    var len = iFlashElementCountArray(aAttributes);
	    if ( len<1 ){
	        return;
	    }

	    // 結合する属性用配列
	    var aAttr = [];
	    // 配列の要素が存在する → 繰り返し
	    for ( var sIndex in aAttributes ){
	        // pluginspageやswliveconnectはembedにしかない属性
	        if ( sIndex == 'pluginspage' || sIndex == 'swliveconnect' ){
	            continue;
	        }
	        // 属性の指定を生成
	        var sAttr = '';
	        if ( sIndex == 'declare' ){
	            // declareには属性値はない
	            if ( aAttributes[sIndex] ){
	                sAttr = 'declare';
	            }else{
	                continue;
	            }
	        }else{
	            sAttr = sIndex + '="' + aAttributes[sIndex] + '"';
	        }
	        aAttr.push(sAttr);
	    }
	    // 配列の要素が存在するかチェック
	    var len = aAttr.length;
	    if ( len<1 ){
	        return;
	    }

	    // 配列あり → object要素を構成
	    var sAttrJoined = aAttr.join(' ');
	    sObjectHTML = '<object ' + sAttrJoined + '>';
	    return;
	};

	/**
     * nFlashElementMakeParam
     *param要素生成する関数
     *
     * @return
     * @type    Function
     * @class   FlashElement
     */
	var nFlashElementMakeParam = function(){

	    // 生成するHTMLの初期化
	    sParamHTML = '';

	    // パースする配列は存在するかチェック
	    if ( ! aParams ){
	        return;
	    }

	    // 配列の要素が存在するかチェック
	    var len = iFlashElementCountArray(aParams);
	    if ( len<1 ){
	        return;
	    }

	    // 結合する属性用配列
	    var aParamElements = [];
	    // 配列の要素が存在する → 繰り返し
	    for ( var sIndex in aParams ){
	        var sParamElement = '';
	        sParamElement = '<param name="' + sIndex + '" value="' + aParams[sIndex] + '">';
	        aParamElements.push(sParamElement);
	    }
	    // 配列の要素が存在するかチェック
	    var len = aParamElements.length;
	    if ( len<1 ){
	        return;
	    }
	    // 配列あり → param要素を構成
	    sParamHTML = aParamElements.join('');
	    return;
	};

	/**
     * nFlashElementMakeEmbed
     * embed要素生成する関数
     *
     * @return
     * @type    Function
     * @class   FlashElement
     */
	var nFlashElementMakeEmbed = function(){

	    // 生成するHTMLの初期化
	    sEmbedHTML = '';

	    // パースする配列は存在するかチェック
	    if ( ! aAttributes ){
	        // 存在しないなんてなし
	        return;
	    }
	    if ( ! aParams ){
	        // 存在しないなんてなし
	        return;
	    }

	    // 結合する属性用配列
	    var aAttr = [];
	    // object要素用の属性をパース
	    // 属性値があるか？
	    var len = iFlashElementCountArray(aAttributes);
	    if ( len>0 ){
	        // 配列の要素が存在する → 繰り返し
	        for ( var sIndex in aAttributes ){
	            // codebaseやclassidはobjectにしかない属性
	            if ( sIndex == 'codebase' || sIndex == 'classid' ){
	                continue;
	            }
	            // 属性の指定を生成
	            var sAttr = '';
	            if ( sIndex == 'declare' ){
	                // declareには属性値はない
	                if ( aAttributes[sIndex] ){
	                    sAttr = 'declare';
	                }else{
	                    continue;
	                }
	            }else if ( sIndex == 'id' || sIndex == 'name' ){
	                sAttr = sIndex + '="' + aAttributes[sIndex] + '_embed"';
	            }else{
	                sAttr = sIndex + '="' + aAttributes[sIndex] + '"';
	            }
	            aAttr.push(sAttr);
	        }
	    }
	    // param要素用の属性をパース
	    // 属性値があるか？
	    var len = iFlashElementCountArray(aParams);
	    if ( len>0 ){
	        // 配列の要素が存在する → 繰り返し
	        for ( var sIndex in aParams ){
	            // wmodeはparamでしか指定できない属性
	            if ( sIndex == 'wmode' ){
	                continue;
	            }
	            // 属性の指定を生成
	            var sAttr = '';
	            sAttr = sIndex + '="' + aParams[sIndex] + '"';
	            aAttr.push(sAttr);
	        }
	    }

	    // 配列の要素が存在するかチェック
	    var len = aAttr.length;
	    if ( len<1 ){
	        return;
	    }

	    // 配列あり → object要素を構成
	    var sAttrJoined = aAttr.join(' ');
	    sEmbedHTML = '<embed ' + sAttrJoined + '>';
	    return;
	};

	/**
     * nFlashElementCombine
     * object要素とparam要素とembed要素を合わせる関数
     *
     * @return
     * @type    Function
     * @class   FlashElement
     */
	var nFlashElementCombine = function(){

	    // 生成するHTMLの初期化
	    sFlashHTML = '';

	    // object要素があるか？
	    if ( sObjectHTML == '' ){
	        // ないならembed要素だけで構成
	        sFlashHTML = sEmbedHTML;
	    }else{
	        // あるならparam要素も挟んで構成
	        sFlashHTML = sObjectHTML + sParamHTML + sEmbedHTML + '</object>';
	    }

	    return;
	};

	/**
     * write
     * object要素/embed要素 を出力する関数
     *
     * @return
     * @access  public
     * @type    Function
     * @class   FlashElement
     */
	that.write = function(aFlashOptions, blSSL){
	
	    // 要素取得
	    var sFlashElement = toString(aFlashOptions, blSSL);
	    // 出力
	    document.write(sFlashElement);
        document.close();
	    return;
	};

	/**
     * toString
     * object要素/embed要素 を返す関数
     *
     * @return  String  sFlashHTML
     * @type    Function
     * @class   FlashElement
     */
	var toString = function(aFlashOptions, blSSL){

	    // 要素生成
	    nFlashElementMake(aFlashOptions, blSSL);
	    // 返す
	    return sFlashHTML;
	};

	/**
     * iFlashElementCountArray
     * 配列の要素を数える関数
     *
     * @return  Integer iCounter
     * @type    Function
     * @class   FlashElement
     */
	var iFlashElementCountArray = function(aTarget){

	    // 存在するものなのかチェック
	    if ( ! aTarget ){
	        return;
	    }
	    var iCounter=0;
	    for ( var sIndex in aTarget ){
	        iCounter++;
	    }
	    return iCounter;
	};
};


