
/////
///// noa.js は NOA 外郭を司るカルテ・ホルダーのようなもの
///// 個々のカルテ記述は chart.js クラスが司る
/////

//////////////////////////////////////////////////////////////
///// URL で受け取るパラメータ //////////////////////////////////

function suppliedPatientId(){
    // URL で与えられた patientId
    return document.getElementById("_pid").value;
}

function addPageFlag(){
    // URL で与えられた「新規ページ追加ステータス」
    return (document.getElementById("_addPage").value)
        ? true : false;
}

///// URL で受け取るパラメータ //////////////////////////////////
//////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////
///// ヘッダー・メニューやツール・メニューから起動される周辺ツール //////

function openToolPane(){
    // tools パネルを開く
    if (floatToolMenu())
        openFloatTools();
    else
        window.open("./tools.php", "tools");
}

///// ヘッダー・メニューやツール・メニューから起動される周辺ツール //////
//////////////////////////////////////////////////////////////


/////////////////////////////////////
///// POLLING ///////////////////////

function pollingWORK(){
    // 受付の患者登録を Worker を使い裏プロセスの polling でチェック
    // DB とのやりとりや polling は polling.js で設定
    var obj = new Object();
    obj["dateTime"] = today();
    var noaString = encodeObject(obj);

    var worker = new Worker('./polling.js');
    worker.postMessage(noaString); // ### worker に命令書 noaString を送る ###

    //_initDebug(true); //##

    worker.onmessage = function (event) {
        // ### worker の処理したデータを受け取る ###
        var answer = event.data; // ### worker からの返答 ###
        var array = answer.split("<SEPARATOR>");
        if (array.length > 1){
            var obj = JSON.parse(array[1]);
            var records = obj.records; // 本日の日計表レコード
            var messageArray = obj.message; // メッセージ・オブジェクト
            
            // 他アプリからのメッセージを表示
            if (messageArray && (messageArray.length > 0)){
                //var found = false;
                for (num in messageArray){
                    var rec = messageArray[num];
                    //alert(encodeObject(rec)); //##
                    
                    var ary = rec.receiver.split("@");
                    var receiver = ary[0];
                    var app = ary[1];
                    if ((receiver == owner()) && (app == "NOA")){
                        showMessenger(rec); // neuron.js
                    }
                }
            }
            
            // 本日の「受診者ポップアップ・タグ」を表示
            if (noCheckWaiting() == 0){
                var elm = document.getElementById("pollingArea");
                elm.innerHTML = "";
                var div = newDIV(elm, "");
                var now = today();
                
                for (num in records){
                    var rec = records[num];
                    var etime = rec.endTime; // 診察終了時刻
                    
                    // 本日のものだけをポップアップ表示
                    if (! isSameDate(rec.entryDate, now)) continue;
                    
                    // 日時でなく年月日で比較
                 //   if (rec.entryDate > rec.updateTime){
                    if (shortDate(rec.entryDate) > shortDate(rec.updateTime)){
                        var sp = newSPAN(div, "/reserved-patient-tab");
                        sp.innerHTML = rec.patientId + " " + rec.kanjiName;
                        // 予約日時で新規ページ追加するかどうか尋ねる
                        if (isAddReservedPage() * 1 > 0){ // localStorage.js
                            // ページ追加
                            var action = open_action(rec.patientId, rec.reservedDate);
                        } else {
                            // ページ追加せず参照のみ
                            var action = open_action(rec.patientId);
                        }
                        sp.setAttribute("onclick", action);
                    } else if (etime && (etime.toString().length > 0)) {
                        // 診療終了したものは表示しない
                    } else {
                        // 診療終了していないものだけを拾い出す：新規ページを追加
                        var sp = newSPAN(div, "/waiting-patient-tab");
                        sp.innerHTML = rec.patientId + " " + rec.kanjiName;
                        var action = open_action(rec.patientId, 'addPage');
                        sp.setAttribute("onclick", action);
                    }
                }
            }
            
            // 待受リストを更新
            refleshWaitingList(records);
        }
        
        function open_action(pid, addPage){
            // カルテを開くアクションを返す
            if (openEachNOA() > 0){ // localStorage.js
                var url = "window.open('top.php";
                url += "?patientId=" + pid;
                if (addPage) 
                    url += "&addPageFlag=" + addPage;
                url += "')";
                
                return url;
            } else {
                if (addPage)
                    return "openChart('" + pid + "','" + addPage + "')";
                else
                    return "openChart('" + pid + "')";
            }
        }
    }
}

///// POLLING ///////////////////////
/////////////////////////////////////

/////////////////////////////////////
///// SEARCH ////////////////////////

var _keyArray;
var _keyPos;

function jumpToKey(keyPos){
    // テキスト中の次のキーへカーソル・ジャンプ
    if (_keyPos * 1 > (keyPos * 1 + 1)){
        var fieldId = _keyArray[(keyPos * 1 + 1)]; // 次のフィールド
        var elm = document.getElementById(fieldId);
        
        // 次のヒット・ページの先頭にジャンプ
        var pos = getPosition(elm.parentNode.parentNode);
        window.scroll(0, pos.y);
    } else {
        window.scroll(0, 0);
    }
}
function searchRecord(key){
    // 全レコードの ProgressSection 中を検索
    //_initDebug(true); //##
    _debug("== searchRecord->"+key); //##
    
    eraseMarks(); // 以前の検索でつけたマークをすべて削除
    
    _keyPos = 0;
    _keyArray = new Array();
    var count = 0;
    var obj = progressObj();
    for (entryDate in obj){
        // rec は ProgressSection と NameSection のデータを保有
        _debug("entryDate->"+entryDate); //##
        
        var rec = obj[entryDate];
        var array = layoutForMode(_progress_);
        for (num in array){
            var layoutObj = array[num];
            //_debug("layoutObj->"+encodeObject(layoutObj)); //##
            if (layoutObj.hitAndRun * 1) continue; // 非表示セルをスキップ
            
            // CELL の VALUE を表示するエリア elm を取得
            var tag = layoutObj.tag;
            var cid = entryDate + "." + tag + ".val";
            var elm = document.getElementById(cid);
            if (!elm) continue; // 値がないため生成されていないセルをスキップ
            
            // vALUE
            var val = elm.innerText;
            
            _debug("-- "+cid+"->"+val); //##
            var ary = val.split(key);
            if (ary.length > 1){
                // 検索キーと一致する文言があれば VALUE 中に action を埋め込む
                var st = '<span style="background-color:#ff0">';
                st += key + '</span>';
                elm.innerHTML = ary.join(st);
                elm.setAttribute("onclick", "jumpToKey('" + _keyPos + "')");
                
                // key にマッチした element の id を記憶
                _keyArray[_keyPos++] = cid;
                
                // key に一致した回数をカウント
                count += (ary.length - 1);
            }
        }
    }
    return count;
    
    
    function eraseMarks(){
        // 以前の検索でつけたマークをすべて削除
        for (num in _keyArray){
            var cid = _keyArray[num];
            var elm = document.getElementById(cid);
            if (elm){
                var ary = cid.split(".");
                var dateTime = ary[0];
                var tag = ary[1] + "." + ary[2]; // "talbe.field" 形式にする
                var obj = valueForTag(tag, dateTime);
                if (!obj) continue;
                
                elm.innerHTML = htmlForValue(obj.val);
                elm.setAttribute("class","cellValue");
                // 過去データなら背景を過去色にする：淡青色
                if (obj && obj.isPast) elm.setAttribute("class", "pastCellValue");
            }
        }
    }
}

function search(){
    // 検索を実行
    var key = document.getElementById("searchF").value;
    if (!key) return;
    
    if (isDigit(key) && (key.length == 8)){
        if (confirm(key + " のカルテを検索しますか")){
            getPatients(key);
            return;
        }
    }
    
    var count = searchRecord(key);
    
    // キーが最初にみつかったページを画面上端に表示
    jumpToKey(-1);
    
    if (count >0)
        alert(key + " が ( " + count + " 件 ) みつかりました。黄色い該当部分をクリックすると次の該当部分へジャンプします");
    else
        alert(key + " に該当する文言は、このカルテ中にありません");
}

///// SEARCH ////////////////////////
/////////////////////////////////////


/////////////////////////////////////
///// FIND PATIENT //////////////////

function closeWorkArea(){
//function closePatientList(){
    // 患者リストを閉じる
    var elm = elmFor("workArea");
    elm.innerHTML = "";
}
function gotPatientList(answer){
	// rowid のレコードをサーバから読込み
	var records = JSON.parse(answer);
    //_debug("== gotPatientList->"+encodeObject(records)); //##
    
    // TOOL AREA の workArea に結果を表示
    var elm = elmFor("workArea");
    elm.innerHTML = "";
    
	var tbl = newTABLE(elm, "/base-table");
    tbl.style.fontSize = "10pt";
    tbl.style.margin = "2px";
    
	var tr = newTR(tbl, "", "");
    tr.style.backgroundColor = "#eee";
	var td = newTD(tr, "", "");
    td.style.width = "150px";
	var im = newIMAGE(td, "icon", "./close.png", "?");
    im.style.height = "12px";
	im.setAttribute("onclick", "closeWorkArea()");
    im.setAttribute("class", "expandIcon");
    var sp = newSPAN(td, "");
    sp.innerHTML = "最終受診日";
    sp.style.paddingLeft = "5px";
    td.style.paddingLeft = "5px";
	var td = newTD(tr, "", "カルテID");
    td.style.width = "100px";
	var td = newTD(tr, "", "氏名");
	
    var srcObj = new Object();
	var patientId, name;
	var count = records.length;
    for (r in records){
		var rec = records[r];
		var kanji = (rec.patientKanjiName) ? rec.patientKanjiName : "";
		patientId = rec.patientId;
        name = kanji;
		var romaji = (rec.patientRomajiName) ? rec.patientRomajiName : "";
		var lvd = (rec.lastVisitDate) ? rec.lastVisitDate : "";
        
        srcObj[rec.patientId] = lvd;
        
		var tr = newTR(tbl, "/record", "");
		tr.setAttribute("onclick", "parent().openChart('" + rec.patientId + "')");
		var td = newTD(tr, "", lvd);
        var td = newTD(tr, "", rec.patientId);
        td.style.paddingLeft = "5px";
		var td = newTD(tr, "", kanji);
	}
    // listMaker へ渡す情報を localStorage に記憶
    setListMakerSrc(srcObj); 
    
	var tr = newTR(tbl, "", "");
    tr.style.backgroundColor = "#ddd";
	var td = newTD(tr, "", "");
    td.style.paddingLeft = "5px";
	td.setAttribute("colspan", "3");
    // listMaker を立ち上げるボタンを生成
    var img = newIMAGE(td, "outArrow", "./outArrow.png", "?");
    img.style.height = "14px";
    img.setAttribute("onclick", "openListMaker()");
    img.setAttribute("class", "expandIcon");
    setInfoTip("outArrow", "検索結果を別パネルで詳細表示"); // INFO
    var sp = newSPAN(td, "");
    sp.innerHTML = records.length + " 件 みつかりました";
    sp.style.paddingLeft = "5px";
    
	if (count == 1){
		// 検索結果が１件のみなら直ちにそのカルテを開く
		parent().openChart(patientId);
	}
}
function showPatientList(){
	// 検索キーにマッチしたカルテのリストを表示
    var searchKey = document.getElementById("keyF").value;
    
    setStoragedKey(searchKey); // localStorage に記憶
    
    closeFloatPanel();
    getPatients(searchKey);
}

function searchPatient(){
    // FRONT の受診者リストを表示
    var w = 250;
	var x = 10; // 表示するx座標
	var y = 30; // 表示するy座標
    var title = "カルテ検索";
    var elm = openSeeThroughPanel("_floatPanel", x, y, w, title);
    if (!elm){
        alert("_floatPanel がないのでパネルを表示できません"); return;
    }
    elm.style.padding = "8px";
    
    var div = newDIV(elm, "");
    var fd = newFIELD(div, "keyF", "", 30, storagedKey());
    fd.setAttribute("class", "searchField");
    fd.setAttribute("onchange", "showPatientList()");
    fd.focus();
    // 検索ボタン
    var bt = newSPAN(div, "/searchButton");
    bt.innerHTML = "検索";
    bt.setAttribute("onclick", "showPatientList()");
}

///// FIND PATIENT //////////////////
/////////////////////////////////////


/////////////////////////////////////
///// ACCESSS LOG ///////////////////

function opneLogChart(mode, patientId, patientName){
    // waitingList accessLog から呼ばれる
    if ((mode == 0) && isShiftDown()){ // mode -- 0:履歴 1:待受
        var st = patientId+ " " + patientName + " の行を削除していいですか";
        if (confirm(st)){
            var args = new Object();
            args["owner"] = cp_owner();
            args["patientId"] = patientId;
            NRCall("REMOVE_ACCESS_LOG", args, gotAccessLog);
        }
    } else {
        closeFloatPanel();
        if (openEachNOA2()) // localStorage.js
            window.open("top.php?patientId=" + patientId, "_blank");
        else
            openChart(patientId);
    }
}

var _accessLog;
function sortAccessLog(){
    // 受付日時で逆ソートする
    var status = (accessLogReverse()) ? "" : "1";
    setAccessLogReverse(status);
    
    var args = new Object();
    args["owner"] = owner();
    args["reverse"] = status;
    NRCall("GET_ACCESS_LOG", args, gotAccessLog);
}

function dateCompare(a, b){
    // a, b を日付で逆順に比較
    
    var dateA = dateWithString(a.date);
    var dateB = dateWithString(b.date);
    
    return (dateA > dateB) ? 0 : 1;
}
function gotAccessLog(answer){
    var x = 10;
    var y = 80;
    var w = 400;
    var title = "受診履歴";
    var action = "openHelp('./accessLogHelp.html')";
    var elm = openSeeThroughPanel("_floatPanel", x, y, w, title, action);
    var div = newDIV(elm, "");
    
    // TITLE
	var tbl = newTABLE(div, "/base-table");
    tbl.style.fontSize = "9pt";
    var tr = newTR(tbl, "", "");
    tr.parentNode.style.borderBottom = "thin solid #888";
    var td = newTD(tr, "bookingSortTab", "参照年月日");
    td.style.width = "140px";
    var td = newTD(tr, "", "カルテID");
    td.style.width = "70px";
    var td = newTD(tr, "", "氏名");
    td.style.width = "150px";
    
    var dv = newDIV(div, "");
	dv.style.height = "200px";
	dv.style.overflow = "auto";
    var tbl = newTABLE(dv, "/base-table");
    tbl.style.fontSize = "9pt";
    
    // RECORDS
    var array = JSON.parse(answer);
    var log = new Array();
    for (num in array){
        var rec = array[num];
        var tr = newTR(tbl, "/logRow", "");
        var action = "opneLogChart(0,'" + rec.pid + "','" + rec.name + "')"
        tr.setAttribute("onclick", action);
        var td = newTD(tr, "", rec.date);
        td.style.width = "140px";
        var td = newTD(tr, "", rec.pid + ""); // 数値だと表示されない
        td.style.width = "70px";
        var td = newTD(tr, "", rec.name);
        td.style.width = "150px";
    }

    // FOOOTER
    var dv = newDIV(elm, "");
    dv.style.fontSize = "9pt";
    dv.style.paddingLeft = "5px";
    dv.style.borderTop = "thin solid #888";
    var sp = newSPAN(dv, "/listMember");
    sp.innerHTML = "逆順に表示";
    sp.setAttribute("onclick", "sortAccessLog()");
    sp.style.marginRight = "10px";
    var cb = newCHECKBOX(dv, "", "カルテを別ウインドーで開く", openEachNOA2());
    cb.setAttribute("onchange", "setOpenEachNOA2(this)");
}

function showAccessLog(){
    // カルテのアクセス・ログを表示：TOOL MENU から使う
    // status が "1" なら逆順にソート
    var status = (accessLogReverse()) ? "1" : "";
    
    var args = new Object();
    args["owner"] = owner();
    args["reverse"] = status;
    NRCall("GET_ACCESS_LOG", args, gotAccessLog);
}

///// ACCESSS LOG ///////////////////
/////////////////////////////////////



function nextTag(tag){
    // NOA 本文内における tag の次の tag を返す：basic ページでは basicPage.js で定義
    var found = false;
    var array = layoutForMode(_progress_);
    for (num in array){
        var layoutObj = array[num];
        if (layoutObj.hitAndRun * 1) continue; // 非表示セルをスキップ
        
        if (found) return layoutObj.tag;
        if (layoutObj.tag == tag) found = true;
    }
    return null;
}

function removeCheck(){
    // 無条件に編集不可のチェックをはずす
    var bid = "pageReadOnlyStatus";
    var bt = newOnButton(bid, "編集可/編集不可", "getOnOff");
}

function showHeaderIcons(toolMenus){
    //function showIconBar(){
    // ヘッダーにアイコン・ギャラリーを表示
    var div = document.getElementById("toolIconArea");
    div.innerHTML = "";
    
    // ### 工場出荷状態だと toolMenus が 空配列 ###
    if (!toolMenus || (toolMenus.length == 0)) toolMenus = menuTemplate();
    
    //alert("showHeaderIcons->"+encodeObject(toolMenus)); //continue; //##
    
    var ul = newUL(div, "/listMembers");
    for (num in toolMenus){
        var cell = toolMenus[num];
        
        if (cell.menuType * 1 != _main) continue;
        if (cell.disabled * 1) continue;
        if (cell.subTitle * 1) continue;
        //alert("cell->"+encodeObject(cell)); //continue; //##
        
        // メニュー項目を生成
        var li = newLI(ul, "", cell.id + "/listMemberIcon");
        
        if (cell.url == "search()"){
            // cell.editor に infoTip に表示する内容が入っている
            setInfoTip(cell.id, cell.editor); // HELP
            
            // これだけは特別扱い
            var dv = newDIV(li, "/searchFrame");
            var fd = newFIELD(dv, "searchF", "", 15, "");
            setInfoTip(cell.id, "このカルテ内の文言検索"); // HELP
            fd.setAttribute("class", "searchField");
            fd.setAttribute("onchange", "search()");
            var bt = newSPAN(dv, "/searchButton");
            bt.innerHTML = "検索";
            bt.setAttribute("onclick", "search()");
        } else if (cell.icon){
            // ICON があれば ICON を表示
            // cell.editor に infoTip に表示する内容が入っている
            setInfoTip(cell.id, cell.editor); // HELP
            var img = newIMAGE(li, "", cell.icon, "icon");
            img.style.margin = "0 5px"; // ボタン間隔
            img.style.height = "15px";
            var action = "kickMenuCell('"+cell.url+"','"+cell.window+"',this)";
            img.setAttribute("onclick", action);
            img.setAttribute("class", "expandIcon");
        } else {
            // アンカー表示
            // cell.editor に infoTip に表示する内容が入っている
            setInfoTip(cell.id, cell.editor); // HELP
            var bt = newDIV(li, "/greenButton");
            bt.innerHTML = cell.label;
            bt.style.position = "relative";
            bt.style.bottom = "1px"; // ボタン位置調整
            if (cell.url){
                var action = "kickMenuCell('"+cell.url+"','"+cell.window+"',this)";
                bt.setAttribute("onclick", action);
            }
        }
    }
    
    // HELP
    var li = newLI(ul, "", "noaHelp/listMemberIcon");
    setInfoTip("noaHelp", "HELP"); // HELP
    var img = newIMAGE(li, "", "help.png", "icon");
    img.style.height = "17px";
    img.setAttribute("onclick", "openHelp('./noaHelp.html')");
    img.setAttribute("class", "expandIcon");
    
    // TOOL MENU
    var li = newLI(ul, "", "gearIcon/listMemberIcon");
    setInfoTip("gearIcon", "Tool Menu"); // HELP
    var img = newIMAGE(li, "", "gear.png", "icon");
    img.style.height = "17px";
    img.setAttribute("onclick", "openToolPane()");
    img.setAttribute("class", "expandIcon");
}

// ###########################################
// ### FireFox 系ブラウザのイベント操作に必要 ######
var _Event = null;
document.onkeyup = function(e){
    　_Event = null;
}
document.onkeydown = function(e){
    　_Event = e;
}
function isShiftDown(){
    // shift が押されていれば true を返す
    var shift;
    
    if (_Event != null){
        shift = _Event.shiftKey;
    } else {
        if (navigator.userAgent.indexOf('Firefox', 0) == -1)
            shift = event.shiftKey;
        else
            shift = false;
    }
    return shift;
}
function eventKeyCode(){
    // keyCode 返す
    if (_Event != null){
        return _Event.keyCode;
    }
    return null;
}
// ### FireFox 系ブラウザのイベント操作に必要 ######
// ###########################################


////////////////////////////////////////////////////////////////////////////
///// SHELL から使えるメソッド ////////////////////////////////////////////////

function getPatients(searchKey){
    // searchKey に相当するカルテをリストアップ：SH で開始する関数は SHELL 対応
    if (searchKey.length){
        // listMaker へ渡す情報を localStorage に記憶
        var st = "カルテ検索（ " + searchKey + " を含む検索結果 ）";
        setListMakerHeader(st); // localStorage に記憶

        get_patients(searchKey, gotPatientList); // サーバでアクセス・ログに記憶
    } else {
        alert("検索キーが指定されていません");
    }
}

///// SHELL から使えるメソッド ////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////


function startupedNOA(answer){
    // NOA が起動された
    var obj = JSON.parse(answer);
    // レイアウトを設定：ページが開かれた時に使われる
    
    //_initDebug(true); //##
    //_debug("startupedNOA layout->"+encodeObject(obj.layout)); //##
    //return; //##

    setLayoutObj(obj.layout); 
    // 施設情報を記憶
    setHospitalInfo(obj.hospitalInfo);
    // ツール・メニュー構造を記憶
    setToolMenus(obj.toolMenus);
    // 一括処理設定があれば取得
    setCalls(obj.calls);
    // 基準値を取得
    setStandardList(obj.standard); // standardCenter.js
    
    // ヘッダーにアイコン・ギャラリーを表示
    showHeaderIcons(obj.toolMenus); 
    
    // 初心者用に NOA ヘルプを表示
    if (showHelp() == 0) openHelp('./noaHelp.html'); 
    
    // DB をチェック：戻値は無し
    NRCall("CHECK_FRONT_TBALE");
    NRCall("CHECK_PRICE_LIST"); // dbName, tableName, fieldName の有無をチェック
    
    // FRONT での新規受付患者をチェック
    pollingWORK(); 
    
    // URL に patientId が指定されていればカルテを開く：waitingList などから使われる
    setCurrentDate(null); // addPage で比較のため使用
    openChart(suppliedPatientId(), (addPageFlag()) ? 'addPage' : null);
}
function initNOA() {
    //_initDebug(true); //##
    var elm = document.getElementById("base");
    elm.innerHTML = "";
    
    // === HEADER =============================
    var div = newDIV(elm, "/title-bar");
    // --- LEFT SIDE ---------------
    var dv = newDIV(div, "/left-side");
    dv.style.width = "110px"; //##
    // patientId
    var pidv = newSPAN(dv, "patientIdArea");
    // --- RIGHT SIDE ---------------
    var dv = newDIV(div, "/right-side");
    dv.style.paddingRight = "10px";
    var dv = newDIV(dv, "toolIconArea"); // 周辺ツール・アイコンを表示するエリア
    
    // === BODY ==============================
    var div = newDIV(elm, "");
    var tbl = newTABLE(div, "/base-table");
    var tr = newTR(tbl, "", "");
    // CALENDAR AREA -------------------
    var td = newTD(tr, "calendarArea", ""); // width は openCalendar() で設定
    // CHART AREA ----------------------
    var td = newTD(tr, "contents", "");
    td.style.clear = "both";
    td.setAttribute("class", "pastColor");

    // 設定された高さを画面スクロール範囲とする
    var val = overFlowHeight();
    if (val >= 100){
        div.style.height = val + "px";
        div.style.overflow = "auto";
    }
    
    // === FOOTER ============================
    var div = newDIV(elm, "/title-bar");
    // LEFT-SIDE
    var dv = newDIV(div, "/left-side");
    dv.innerHTML = hospitalName() + " ( 取扱者 " + userName() + " )";
    dv.style.width = "500px";
    // RIGHT-SIDE
    var dv = newDIV(div, "version/right-side");
    dv.innerHTML = version();
    
    // NOA のレイアウト・ツールメニュー・ヘッダーアイコン・HospitalInfo をリクエスト
    //NRStartupNOA(owner(), hospitalId(), startupedNOA);

    var args = new Object();
    args["owner"] = owner();
    args["hospitalId"] = hospitalId();
    NRCall("STARTUP_NOA", args, startupedNOA);
}

function version(){
	return "Ver.140706";
}
