/* -*- javascript -*-
  MemoLi
  PC用トップページ
*/

/**************************************************************/
(function (){
    // [定数] 新着メモ取得 API の URL
    var MEMO_LATEST_URL = '../api/latest.php';
    
    
    /**********************************************************/
    /* ユーティリティ                                                */
    /**********************************************************/
    // [関数] XMLHttpRequest 生成
    function newXMLHttpRequest()
    {
        if (window.ActiveXObject){
            try{
                //MSXML2以降用
                return new ActiveXObject( 'Msxml2.XMLHTTP' );
            }catch (e){
                try{
                    //旧MSXML用
                    return new ActiveXObject( 'Microsoft.XMLHTTP' );
                }catch (e2){
                    return null;
                }
            }
        }else if(window.XMLHttpRequest){
            //Win ie以外のXMLHttpRequestオブジェクト実装ブラウザ用
            return new XMLHttpRequest();
        }else{
            return null;
        }
        // 引用元: http://allabout.co.jp/internet/javascript/closeup/CU20050515A/
    }

    // [関数] JSON 形式応答を解析
    function parse_json_response( request )
    {
        // チェック
        if ( request.status != 0 && request.status != 200
             || request.responseText.length == 0 ){
            return null;  // エラー
        }
        
        // JSON 解析
        return eval( '(' + request.responseText + ')' );
    }

    // [関数] 要素のテキストを変更
    function set_text_content( element, text )
    {
        if ( element.textContent != undefined ){
            element.textContent = text;
        }else{
            element.innerText = text;
        }
    }

    // [関数] テンプレート適用
    function apply_template( template, param, repo )
    {
                function _apply( node )
        {
            // 子
            for ( var child = node.firstChild; child;
                  child = child.nextSibling ){
                if ( child.nodeType == 1/*Node.ELEMENT_NODE*/ ){
                    _apply( child );
                }
            }
            
            // 自分自身   name 属性を使用してテキストを置換する
            if ( node.nodeType == 1/*Node.ELEMENT_NODE*/ ){
                var name = node.getAttribute( 'name' );
                if ( name && param[name] != undefined ){
                    set_text_content( node, param[name] );
                }
                if ( name && repo ){ repo[name] = node; }
            }
            
            return node;
        }
        
        //
        return _apply( template.cloneNode( true ) );
    }

    // [関数] 数値(0もしくは正数)=>カンマ区切りの数値文字列に変換
    function to_display_number( num )
    {
        var result = '';
        
        while ( num > 999 ){
            var section = num % 1000;
            if ( section < 10 ){
                section = '00' + section;
            }else if ( section < 100 ){
                section = '0' + section;
            }
            
            result = ',' + section + result;
            num = Math.floor( num / 1000 );
        }
        if ( result == '' || num > 0 ){
            result = num + result;
        }
        
        return result;
    }

    // [関数] 日付時刻を YY-MM-DD hh:mm 形式の文字列に変換
    function to_display_timestamp( date )
    {
        var YY = date.getFullYear();
        var MM = date.getMonth() + 1;   if ( MM < 10 ){ MM = '0' + MM; }
        var DD = date.getDate();        if ( DD < 10 ){ DD = '0' + DD; }
        var hh = date.getHours();       if ( hh < 10 ){ hh = '0' + hh; }
        var mm = date.getMinutes();     if ( mm < 10 ){ mm = '0' + mm; }
        
        return YY+'-'+MM+'-'+DD+' '+hh+':'+mm;
    }
    
    // [関数] メモ本文・コメント本文を指定要素の子に挿入
    function insert_multiline_text( element, text )
    {	
		// \nを<br />へ全て置き換える（gオプションを忘れずに！）
        var content = text.replace( "\n", "<br />", 'g' );
        
        /*for ( var i = 0; i < content.length; ++i ){
			
			// にっこり
			var fi_nikkori = content[i].indexOf("##PC_NIKKORI##");
			
			// にっこりマークが見つかったら
			if ( fi_nikkori >= 0 ){
				var x = document.createElement( 'img' );
				x.setAttribute('src', "/pc/img/emoji/2f649.gif");
				element.appendChild(x);
				content[i] = content[i].replace("##PC_NIKKORI##", "");
			}

			// びっくり
			var fi_bikkuri = content[i].indexOf("##PC_BIKKURI##");
			
			if ( fi_bikkuri >= 0 ){
				var x = document.createElement( 'img' );
				x.setAttribute('src', "/pc/img/emoji/2f3f1.gif");
				element.appendChild(x);
				content[i] = content[i].replace("##PC_BIKKURI##", "");
			}
			
            if ( i > 0 ){
                element.appendChild( document.createElement( 'br' ) );
				
				var p = document.createElement( 'p' );
				p.setAttribute('id', i);
				element.appendChild( p );
				
				
            }
            //element.appendChild( document.createTextNode( content[i] ) );
        }*/
		element.innerHTML = content;
    }
    
    

    /**********************************************************/
    /* メイン                                                    */
    /**********************************************************/
    // ★変数
    var request;                    // XMLHttpRequest
    var memo_total_div;             // メモ総数の <div>
    var memo_total;                 // メモ総数の要素
    var memo_total_updated;         // メモ総数更新時刻の要素
    var latest = { tuples: [] };    // 新着メモ管理オブジェクト
          // .div                   // 新着メモの <div>
          // .full_div              // 本文表示部の <div>
          // .template              // 新着メモのテンプレート (ヘッダ部)
          // .memo_template         // メモテンプレート
          // .comment_template      // コメントテンプレート
          // .parent                // 挿入ポイント(親)
          // .insptr                // 挿入ポイント(最後の要素)
          // .tuples                // 行の配列
    var top_map = {};               // 表示している地図の情報
          // .img                   // 地図 <img>
          // .href                  // 元々の　href

    // ★初期化処理
    // XMLHttpRequest 生成
    request = newXMLHttpRequest();
    if (!request){ return; }    // あきらめる
    
    // イベントリスナをインストール
    if (window.addEventListener){
        window.addEventListener( 'load', onload, false );
    }else if (window.attachEvent){
        window.attachEvent( 'onload', onload );
    }else{
        window.onload = onload;
    }


    /**********************************************************/
    // [イベント] ウィンドウ表示完了
    function onload()
    {
        latest.div          = document.getElementById( 'new-memo' );
        
        // メモ総数
        memo_total_div      = document.getElementById( 'memo-total-div' );
        memo_total          = document.getElementById( 'memo-total' );
        memo_total_updated  = document.getElementById( 'memo-total-updated' );
        
        // メモリスト
        latest.list_div     = document.getElementById( 'new-memo-list' );
        latest.template     = document.getElementById( 'memo-list-template' );
        latest.parent       = latest.template.parentNode;
        latest.insptr       = latest.template.nextSibling;
        latest.template.removeAttribute( 'id' );
        latest.parent.removeChild( latest.template );
        
        // コメント
        latest.comment_template=document.getElementById( 'comment-template' );
        latest.comment_template.removeAttribute( 'id' );
        latest.comment_template.parentNode
                               .removeChild( latest.comment_template );
        
        // メモ本文
        latest.full_div     = document.getElementById( 'memo-full' );
        latest.memo_template= document.getElementById( 'memo-template' );
        latest.memo_template.removeAttribute( 'id' );
        latest.memo_template.parentNode.removeChild( latest.memo_template );
        
        // 地図
        top_map.img         = document.getElementById( 'top-map' );
        top_map.src         = top_map.img.src;
        
        // 最新情報取得
        retrieve_latest();
    }
    
    // [操作] 新着メモ取得
    function retrieve_latest(){
        // メモ総件数取得
        request.open( 'GET', MEMO_LATEST_URL, true );
        request.onreadystatechange = function(){
            if ( request.readyState == 4/*受信完了*/ ){
                // 解析・更新
                var response = parse_json_response( request );
                if (response){
                    update_memo_count( response );      // メモ総数更新
                    update_memo_latest( response );     // 新着メモ更新
                }
            }
        };
        request.send( null );
    }

    // [操作] メモ総数を更新
    function update_memo_count( response )
    {
        var total = parseInt( response.total );
        var updated = parseInt( response.date );
        if ( isNaN( total ) || isNaN( updated ) ){ return; }    // 形式不正
        
        // HTML に記入
        if ( update_memo_count._last_memo_count == undefined ||
             update_memo_count._last_memo_count != total ){
            // メモ総数
            set_text_content( memo_total, to_display_number( total ) );
            
            // 更新時刻
            var date = new Date( updated * 1000 );
            set_text_content( memo_total_updated,
                              '(' + to_display_timestamp( date ) + ')' );
        }
        
        if ( update_memo_count._last_memo_count == undefined ){
            // メモ総数 div を見せる
            memo_total_div.style.display = 'block';
        }
        
        update_memo_count._last_memo_count = total;
    }

    // [操作] 新着メモを更新
    function update_memo_latest( response )
    {
        if ( !response.data || !( response.data.length > 0 ) ){
            return;                         // 形式不正/メモなし
        }
        
        // 古いエントリを削除
        while ( latest.tuples.length ){
            latest.parent.removeChild( latest.tuples.pop() );
        }
        
        // 挿入
        var i;
        for ( i = 0; i < response.data.length; ++i ){
            var memo = response.data[i];
            
            // テンプレート適用
            var date = new Date( memo.date * 1000 );
            var hh = date.getHours();   if ( hh < 10 ){ hh = '0' + hh; }
            var mm = date.getMinutes(); if ( mm < 10 ){ mm = '0' + mm; }
            
            var param = { title: memo.short_title,
writer: memo.writer,
                          date: hh + ':' + mm,
                          timestamp: to_display_timestamp( date ),
                          prefecture: '(' + memo.prefecture + ')',
                          address: memo.address };
            var repo = {};
            var tuple = apply_template( latest.template, param, repo );
            
            // 本文をインストール
            param.title = memo.title;
            repo.title.onclick = create_on_click( param, memo );
            
            // 挿入
            latest.parent.insertBefore( tuple, latest.insptr );
            latest.tuples.push( tuple );
        }
        
        // 見せる
        latest.div.style.display = 'block';
    }
    
    // [ファクトリ] メモリスト onclick ハンドラを生成
    function create_on_click( param, memo )
    {
        var body = null;
        
        // 本文表示
        function appear()
        {
            // 新着メモリストを非表示にして本文を挿入
            latest.list_div.style.display = 'none';
            latest.full_div.style.display = 'block';
            latest.full_div.appendChild( body );
            
            // 地図を交換
            top_map.img.src = '../api/map.php?lat=' + memo.lat
                            + '&lon=' + memo.lon
                            + '&token=' + memo.token;
                                
            return false;
        }
                
        // 本文削除
        function dismiss()
        {
            // 本文を削除して新着メモリストを表示する
            body.parentNode.removeChild( body );
            latest.list_div.style.display = 'block';
            
            // 地図を交換
            top_map.img.src = top_map.src;
            
            return false;
        }
        
        // ハンドラ
        return function(){
            if (!body){
                // 本文生成
                var repo = {};
                body = apply_template( latest.memo_template, param, repo );
                repo['back-link'].onclick = dismiss;
                repo.address.href
                    = 'http://maps.google.co.jp/maps?ie=UTF8&ll='
                        + memo.lat + ',' + memo.lon + '&z=15';
                
                // 本文展開
                insert_multiline_text( repo.content, memo.body );
                
                // 画像
                if ( memo.image ){
                    repo.image.src = '../api/image.php?image=' + memo.image
                                                            + '&maxwidth=240';
                    repo['image-div'].style.display = 'block';
                }else{
                    repo['image-div'].style.display = 'none';
                }
                
                // コメント展開
                if ( memo.comments ){
                    var insptr = repo.heading;
                    
                    for ( var i = 0; i < memo.comments.length; ++i ){
                        var comment = memo.comments[i];
                        
                        // テンプレート適用
                        var date = new Date( comment.date * 1000 );
                            date = to_display_timestamp( date );
                        var comment_param = { timestamp: date, writer: comment.writer};
                        var comment_repo = {};
                        
                        var contents = apply_template( latest.comment_template,
                                                       comment_param,
                                                       comment_repo );
                        
                        // コメント本文
                        insert_multiline_text( comment_repo.content,
                                               comment.body );
                        
                        // 画像
                        if ( comment.image ){
                            comment_repo.image.src
                                = '../api/image.php?image=' + comment.image
                                + '&maxwidth=240';
                            comment_repo['image-div'].style.display = 'block';
                        }else{
                            comment_repo['image-div'].style.display = 'none';
                        }
                        
                        // 挿入
                        insptr.parentNode.insertBefore( contents,
                                                        insptr.nextSibling );
                        insptr = contents;
                    }
                    
                    repo['comment-div'].style.display = 'block';
                }else{
                    repo['comment-div'].style.display = 'none';
                }
            }
            
            appear();
            return false;
        };
    }
})();
