
var _modeObj = {"以下とは共存できない":"remove","以下もあってよい":"add"};
var _byoumei = 1;

/*
var _filterObj = {"60:子宮内膜組織採取":{"mode":"remove","children":["60:子宮頸管粘液採取"]},"60:コルポスコピー":{"mode":"remove","children":["41:腟洗浄"]},"60:ＡＢＯ":{"mode":"add","children":["60:アルカリホスファターゼ","60:ＣＡ１２５"]}};
 */
var _filterObj;
function setFilterObj(obj){
    /* サーバから読み込んだフィルター構造を以下の形式で _filterObj に記憶
    _filterObj = {"60:子宮内膜組織採取":{"mode":"remove","children":["60:子宮頸管粘液採取"]},"60:コルポスコピー":{"mode":"add","children":["41:腟洗浄"]}}; */
    _filterObj = new Object();
    for (keyAndName in obj){
        var rec = JSON.parse(obj[keyAndName]);
        
        _filterObj[keyAndName] = rec;
    }
    //_debug("== setFilterObj == "+encodeObject(_filterObj)); //##
}
function filterObj(){
    // フィルター機能を実現するオブジェクト
    return _filterObj;
}
function hasFilter(){
    // filter() を機能させるには true を返す
    var status = vinFilterEnabled(); // localStorage
    return (status) ? true : false;
    // return (_filterObj) ? true : false;
}
function filterKeys(){
    // フィルター・キーの配列を返す
    var array = allKeys(_filterObj);
    array.splice(0,0,"");
    array.push("...その他");
    
    return array;
}
function filterForKey(key){
    // key に対応するフィルター・オブジェクトを返す
    return _filterObj[key];
}

var _conditions;
var _conditionRow;
function initCondition(){
    // 条件を初期化：フィルター
    _conditions = new Array();
    _conditionRow = 0;
}
function setConditionRow(row){
    _conditionRow = row;
}
function conditionRow(){
    // 条件要素の行番号を返す
    // ０番は親要素
    return _conditionRow;
}

var _currentDiseases;
function setCurrentDiseases(array){
    // カルテの当日の病名の配列を記憶
    _currentDiseases = array;
}
function hasDisease(disease){
    // カルテの当日の病名に disease があれば true を返す
    for (num in _currentDiseases){
        var name = _currentDiseases[num];
        if (disease == name) return true;
    }
    return false;
}


function makeFilterObj(){
    // 編集されたフィルターをオブジェクトにして返す
    var rec = new Object();
    var key;
    
    for (row in _conditions){
        var obj = _conditions[row];
        if (obj.code * 1 == 0) continue; // 空行はスキップ
        
        if (row == 0){ // 親条件
            if (obj.comment) // 病名の場合
                key = obj.code+":"+obj.name+":"+obj.comment;
            else // 通常
                key = obj.code+":"+obj.name;
            
            rec[key] = new Object();
            rec[key].children = new Array();
        } else { // 子条件
            rec[key].children.push(obj.code+":"+obj.name);
        }
    }
    
    // モード
    var label = document.getElementById("modePop").value;
    rec[key].mode = (_modeObj[label]) ? _modeObj[label] : "";
    
    var result = new Object();
    result.key = key;
    result.value = rec[key];
    
    return result;
}

//////////////////////////////////////////////////////
// Ajax //////////////////////////////////////////////

var _currentRow;
function gotNameList(answer){
	// アイテムリストを表示する
	if ((xmlHttpObject.readyState == 4) && (xmlHttpObject.status == 200)){
		var value = xmlHttpObject.responseText;
		var array = value.split("<SEPARATOR>");
		if (array.length > 1){
			var elm = document.getElementById("nameArea" + _currentRow);
			elm.innerHTML = "";
            
			var obj = JSON.parse(array[1]);
			// obj は {"再診料":"saishin",,} のようなオブジェクトの配列
			var items = new Array();
			for (title in obj){
				var value = obj[title];
                if (title.length ==0) continue;
                
				items.push(title);  // title:"再診料"
			}
			items.splice(0, 0, "");
			items.push("...その他");
            
			// item 選択ポップアップを表示
            var fobj = _conditions[_currentRow];
            var item = (fobj) ? fobj.name : "";
			var pu = newPopupMenu(elm, "namePop" + _currentRow, items, item);
            pu.setAttribute("onchange", "changedName(this,'" + _currentRow + "')");

			// 絞り込みフィールドを生成
			// makeForcusOnArea();

			document.getElementById("message").innerHTML = "";
		}
	} else
		document.getElementById("message").innerHTML = "Loading...";
}
function getNameList(row, code){
	// 診療行為マトリックスの選択で起動され、該当アイテムリストをリクエスト
    var args = new Object();
    args.code = code;
    _currentRow = row;
    
    NRCallVin("GET_CHILD_SELECTOR", args, gotNameList);
}

function savedConditions(answer){
    // フィルター編集パネルを再表示
    //alert("savedConditions->"+answer); //##

    document.getElementById("_floatPanel").innerHTML = "";
    openFilter();
}
function saveConditions(){
    // 設定した条件をフィルターとして保存
    // rec={"60:頸管粘液":{"children":["41:腟洗","60:血型"],"mode":"remove"}} 型式
    var rec = makeFilterObj();

    //_initDebug(true); //##
    //alert("saveConditions ->"+rec.key+"->"+encodeObject(rec.value)); //##

    var args = new Object();
    args["key"] = rec.key;
    args["value"] = rec.value;
    
    NRCall("PUT_VIN_FILTER", args, savedConditions);
}

function gotFiter(answer){
    var obj = JSON.parse(answer);
    //_initDebug(true); //##
    _debug("== gotFilter == "+ encodeObject(obj)); //##
    
    setFilterObj(obj);
    getDiseases();
    
    var elm = document.getElementById("filterListArea");
    if (!elm) return; // getFiter() が vin.js から呼ばれた場合

    // LABEL
    var sp = newSPAN(elm, "");
    sp.innerHTML = "FILTER";
    sp.style.paddingRight = "5px";
    sp.setAttribute("onclick", "_showInfo()"); //##
    
    // KEY ポップアップ
    var pu = newPopupMenu(elm, "listPop", filterKeys(), "");
    pu.setAttribute("onchange", "listSelected(this)");
}
function getFiter(){
    // フィルターをサーバへリクエスト
    var args = new Object();
    NRCall("GET_VIN_FILTER", args, gotFiter);
}

function getDiseases(){
    // 本日カルテの傷病名をサーバへリクエスト
    var tags = "ProgressSection.disease"; // "item1,item2" のようなカンマ区切り形式
    var obj = parent().valueForTag("ProgressSection.disease", parent().currentDate());
    var val = (obj && obj.value) ? obj.value : "";

    var diseases = new Array();
    var array = val.split("<br>");
    for (row in array){
        var ln = array[row]; // "年月日 病名" 形式
        var ary = ln.split(" ");
        var name = ary[1];
        diseases.push(name);
    }
    setCurrentDiseases(diseases);
    //_debug("== getDiseases == "+encodeObject(_currentDiseases));
}


// Ajax //////////////////////////////////////////////
//////////////////////////////////////////////////////


///////////////////////////////////////////////////////
///// filtering ///////////////////////////////////////

function filter(records){
    // buff にフィルターを掛ける
    // return records; // ### フィルター機能を働かせない場合 ###
    
    //_initDebug(false); //##
    _debug("=== source ===");
    
    // 診療行為と行数の対応配列を生成
    var obj = new Object();
    for (row in records){
        var rec = records[row];
        
        // 自費には適用しないなら rec.isOwn でコントロール
        var key = rec.code + ":" + rec.name;
        obj[key] = row;
        
        _debug(key+"->"+row+" isOwn: "+rec.isOwn);
    }
    
    _debug("=== filtering ================");
    var filtObj = filterObj();
    for (key in filtObj){
        // key = "code:name:comment" 型式
        var fobj = filtObj[key];
        var ary = key.split(":");
        var code = ary[0] * 1;
        var name = ary[1];
        var comment = ary[2];
        if (code == 1){
            // フィルター・ラベルが病名だった
            if (hasDisease(name)){
                _debug(name + " がヒット->"+encodeObject(fobj)); //##
                var array = fobj.children;
                for (num in array){ // フィルターの子条件をスキャン
                    var target = array[num]; // フィルターの子条件
                    _debug(key+"->"+fobj.mode + "->" + target); //##
                    if (fobj.mode == "remove"){
                        removeTarget(code + ":" + name, target, comment);
                    } else if (fobj.mode == "add"){
                        // records 中に rec が見つからなければ追加
                        var rec = recordForTarget(target);
                        addTarget(code + ":" + name, target, rec, comment);
                    }
                }
            }
        } else {
            if (obj[key] || (sourceHasSameCode(obj, code, name))){
                // フィルター・ラベルに対応する診療行為があった
                var array = fobj.children;
                for (num in array){ // フィルターの子条件をスキャン
                    var target = array[num]; // フィルターの子条件
                    _debug(key+"->"+fobj.mode + "->" + target); //##
                    if (fobj.mode == "remove"){
                        removeTarget(key, target);
                    } else if (fobj.mode == "add"){
                        // records 中に rec が見つからなければ追加
                        var rec = recordForTarget(target);
                        addTarget(key, target, rec);
                    }
                }
            }
        }
    }
    
    // ### 検証用 ###
    _debug("=== result ================");
    for (num in records){
        var rec = records[num];
        _debug(num+"->"+rec.code + ":" + rec.name);
    }
    
    return records;
    
    function sourceHasSameCode(obj, code, name){
        // code だけで name の指定されていない時に作用
        // すなわちソースに同じ code が存在するかどうかを検証
        if (name.length)
            return false;
        
        // obj の中に code と一致するコードがあれば true を返す
        for (key in obj){
            var ary = key.split(":");
            var cd = ary[0] * 1;
            
            if (cd == code) return true;
        }
        return false;
    }
    
    function addTarget(key, target, record, comment){
        // records へ record をひとつのみ追加
        var hasTarget = false;
        for (row in records){
            var rec = records[row];
            var codeAndName = rec.code + ":" + rec.name;
            
            if (codeAndName == target) hasTarget = true;
        }
        
        if (!hasTarget){
            if (comment){
                if (confirm("「"+key + "」があるので " + comment + "「" + target + "」を追加します")){
                    records.push(record);
                }
            } else if (confirm("「"+key + "」があるので「" + target + "」を追加します")){
                records.push(record);
            }
            _debug("addTarget->"+encodeObject(record));
        }
    }
    
    function removeTarget(key, target){
        // records から target を削除：複数あってもすべて削除
        var hasTarget = false;
        var array = new Array();
        for (row in records){
            var rec = records[row];
            var aKey = rec.code + ":" + rec.name;
            
            // target 以外を array へ収納
            if (aKey == target)
                hasTarget = true;
            else
                array.push(rec);
        }
        if (comment){
            if (confirm("「"+key + "」があるので " + comment + "「" + target + "」を削除します")){
                records = array;
            }
        } else if (hasTarget && confirm("「"+key + "」があるので「" + target + "」を削除します")){
            records = array;
        }
    }
    
    function recordForTarget(target){
        // "60:ＡＢＯ" 型式の target から Vin で扱う型式へ変換
        var ary = target.split(":");
        var code = ary[0];
        var name = ary[1];
        // isOwnFee_|_code_|_alias_|_name_|_dose_|_unitName_|_freq_|_point_|_isMix
        var origin = "_|_"+code+"_|__|_"+name+"_|_1_|__|__|__|_";
        
        /* rec は以下の形式
         origin(isOwnFee_|_code_|_alias_|_name_|_dose_|_unitName_|_freq_|_point_|_isMix)
         number(1)
         subItems()
         isOwn(0)
         code(48)
         alias(kuromai)
         name(クロマイ腟錠１００ｍｇ)
         dose(1)
         standard(1)
         unitName(錠)
         freq(1)
         point(7)
         isMix(0)
         editable(0)
         */
        var rec = new Object();
        rec.origin = origin;
        rec.isOwn = "0";
        rec.code = code;
        rec.name = name;
        rec.dose = "1";
        
        return rec;
    }
}

///// filtering ///////////////////////////////////////
///////////////////////////////////////////////////////


//////////////////////////////////////////////////////
// EDITOR ////////////////////////////////////////////

var _codeNameArray;
function codeNameArray(){
    // コード名の配列を返す
    if (!_codeNameArray){
        _codeNameArray = [""];
    
        var array = codeArray();
        for (num in array){
            var code = array[num];
            _codeNameArray.push(codeName(code));
        }
        _codeNameArray.push("病名");
    }
    
    return _codeNameArray;
}

function changedCode(elm, row){
    // code が変更された
    var codeName = elm.value;
    
    if (codeName == "病名"){
        _conditions[row].code = _byoumei;　// row 位置のフィルター・オブジェクト

        get_menu(parent().owner(), "ProgressSection.disease", gotDiseaseMenu);
    } else {
        var code = codeForName(codeName);
        _conditions[row].code = code;　// row 位置のフィルター・オブジェクト
        
        if (code) getNameList(row, code);
    }
}
function changedName(elm, row){
    // name が変更された
    var codeName = document.getElementById("codePop" + row).value;

    if (codeName == "病名"){
        // 病名の場合は「入力時コメント」がつく
        _conditions[row].name = document.getElementById("namePop0").value;
        _conditions[row].comment = document.getElementById("commentF").value;
    } else {
        _conditions[row].name = elm.value;
    }
    //alert("name->"+_conditions[row].name+" comment->"+_conditions[row].comment); //##
}

function removedCondition(answer){
    // フィルター編集パネルを再表示
    //alert("removedCondition->"+answer); //##
    
    document.getElementById("_floatPanel").innerHTML = "";
    openFilter();
}
function removeCondition(row){
    // row の条件を削除し再表示
    if (row == 0){
        var array = new Array();
        array.push(_conditions[0].code);
        array.push(_conditions[0].name);
        if (_conditions[0].comment) array.push(_conditions[0].comment);

        var key = array.join(":");
        if (confirm("「" + key + "」のフィルターを削除")){
            // value が null なら key に相当するレコードを削除
            var args = new Object();
            args["key"] = key;
            args["value"] = null;
            
            NRCall("PUT_VIN_FILTER", args, removedCondition);
        }
    } else {
        if (confirm("この行を削除していいですか " + row)){
            _conditions.splice(row, 1);
            
            // --- children 各行を生成 -------------------
            var elm = document.getElementById("childrenArea");
            elm.innerHTML = "";
            _conditionRow = 1; // KEY 行の次の children 行から始める
            for (row in _conditions){
                if (row == 0) continue; // KEY 行はスキップ
                
                var obj = _conditions[row];
                makeConditonRow(elm, obj.code + ":" + obj.name);
            }
        }
    }
}

function makeConditonRow(div, label){
    // "60:子宮頸管粘液採取" のようなラベル名を元に条件設定行を生成
    var row = conditionRow(); // 現在の条件設定行の位置
    // フィルター・オブジェクトを生成
    var obj = new Object();
    
    if (label){
        var array = label.split(":");
        obj.code = array[0];
        if (obj.code * 1 == 1){
            var cname = "病名";
            obj.name = array[1];
            obj.comment = array[2];
        } else {
            var cname = codeName(obj.code);
            obj.name = array[1];
        }
    } else {
        obj.code = "0";
        var cname = "";
        obj.name = "";
        obj.comment = "";
    }
    
    var dv = newDIV(div, "");
    dv.style.fontSize = "9pt";
    
    // 削除アイコン
    var img = newIMAGE(dv, "", "./remove-field.png", "X");
    img.style.height = "13px";
    img.setAttribute("onclick", "removeCondition(" + row + ")");
    img.style.marginRight = "2px"; //##

    // コード名
    var pu = newPopupMenu(dv, "codePop" + row, codeNameArray(), cname);
    pu.setAttribute("onchange", "changedCode(this,'" + row + "')");
    
    // 診療行為名
    var sp = newSPAN(dv, "nameArea" + row);
    var bt = newSPAN(sp, "");
    bt.innerHTML = obj.name;
    bt.setAttribute("onclick", "getNamePop('" + row + "')");

    // 入力時説明
    if (obj.comment){
        var dv1 = newDIV(sp, ""); // nameArea に従属
        var sp = newSPAN(dv1, "");
        sp.innerHTML = "入力時説明 ";
        sp.style.verticalAlign = "top";
        var fd = newTEXTAREA(dv1, "commentF", 30, 3, obj.comment);
        fd.setAttribute("onchange", "changedName(this,'0')");
    }
    
    // フィルター・オブジェクトを _conditions に記憶
    _conditions[row] = obj;
    
    // 条件設定の対象行をインクリメント
    setConditionRow(row + 1);
}

function gotDiseaseMenu(answer){
    var obj = JSON.parse(answer);
    
    var menus = new Array();
    for (num in obj){
        var rec = obj[num];
        if (rec.menu.length)
            menus.push(rec.menu);
    }
    //alert("gotDiseaseMenu->"+encodeObject(menus)); //##
    
    // 病名選択ポップアップを表示
    var elm = document.getElementById("nameArea0");
    elm.innerHTML = "";
    
    var fobj = _conditions[0];
    var name = (fobj) ? fobj.name : "";
    
    var pu = newPopupMenu(elm, "namePop0", menus, name);
    pu.setAttribute("onchange", "changedName(this,'0')");
    
    // コメント入力欄
    var div = newDIV(elm, "");
    var sp = newSPAN(div, "");
    sp.innerHTML = "入力時説明 ";
    sp.style.verticalAlign = "top";
    var fd = newTEXTAREA(div, "commentF", 30, 3, fobj.comment);
    fd.setAttribute("onchange", "changedName(this,'0')");
}
function getNamePop(row){
    // row 行に namePop を表示
    var obj = _conditions[row];
    
    if (obj.code * 1 == 1){ // 病名の場合
        get_menu(parent().owner(), "ProgressSection.disease", gotDiseaseMenu);
    } else {
        getNameList(row, obj.code);
    }
}

function addCondition(){
    // 条件設定行を追加
    var elm = document.getElementById("childrenArea");
    
    makeConditonRow(elm, "");
}

function setConditionPane(key){
    // 条件設定ペーンを表示
    initCondition();
    
    if (key == "...その他"){
        key = null;
        var obj = new Object();
        obj.children = new Array();
        obj.children.push("");
    } else {
        var obj = filterForKey(key);
    }
    
    // --- key 行を生成 -------------------
    var elm = document.getElementById("keyArea");
    elm.innerHTML = "";
    elm.style.fontSize = "9pt";
    // コード名
    var div = newDIV(elm, "");
    makeConditonRow(div, key);

    // --- mode 行を生成 -------------------
    var div = newDIV(elm, "");
    div.style.fontSize = "9pt";
    var sp = newSPAN(div, "");
    sp.innerHTML = "が存在したなら";
    sp.style.padding = "0 5px 0 10px";
    // ターゲット
    var st = modeLabel(obj.mode);
    var pu = newPopupMenu(div, "modePop", allKeys(_modeObj), st);
    
    // --- children 行を生成 -------------------
    var div = newDIV(elm, "childrenArea");
    for (num in obj.children){
        var val = obj.children[num];
        
        makeConditonRow(div, val);
    }

    function modeLabel(mode){
        // 例えば "remove" に対応する "以下とは共存できない" を返す
        for (label in _modeObj){
            var md = _modeObj[label];
            if (mode == md) return label;
        }
        return "";
    }
}

function listSelected(menu){
    // フィルターのリストが選択された
    var elm = document.getElementById("filterContentsArea");
    elm.innerHTML = "";

    // key を表示するエリア
    var div = newDIV(elm, "keyArea");
    var key = menu.value;
    setConditionPane(key);

    // 追加ボタン
    var div = newDIV(elm, "");
    div.style.padding = "5px 0";
    var img = newIMAGE(div, "", "./add-field.png", "X");
    img.style.height = "15px";
    img.setAttribute("onclick", "addCondition()");
    
    // 確定ボタン
    var div = newDIV(elm, "");
    div.style.textAlign = "right";
    var bt = newDIV(div, "/fixButton");
    bt.innerHTML= "以上の条件でフィルター設定";
    bt.setAttribute("onclick", "saveConditions()");
    bt.style.padding = "8px 10px 3px 10px";
    bt.style.marginBottom = "5px";
}

function _showInfo(){
    // フィルター・オブジェクトの内容を確認のため表示
    var rec = makeFilterObj();
    
    //_initDebug(true); //##
    _debug("save conditions ->"+rec.key+"->"+encodeObject(rec.value)); //##
}

function openFilter(){
    // フィルター設定パネルを開く
    var panel = document.getElementById("_floatPanel");
    if (panel.innerHTML.length){
        closeFloatPanel();
        return;
    }
    
    var w = 320;
	var x = 5; // 表示するx座標
	var y = 20; // 表示するy座標
    var elm = openSeeThroughPanel("_floatPanel", x, y, w, "フィルター編集","openHelp('vinFilterHelp.html')");
	elm.style.opacity = "1.0"; // dom.js を上書き
	elm.style.backgroundColor = "#ffd"; // dom.js を上書き
	elm.style.padding = "5px";
	elm.style.marginTop = "5px";
	elm.style.borderRadius = "5px";
    
    // フィルターのリスト表示エリア
    var div = newDIV(elm, "filterListArea");
    div.style.marginBottom = "5px";
    div.style.fontSize = "9pt";

    // フィルターの内容表示エリア
    var div = newDIV(elm, "filterContentsArea");

    // チェックボックス
    var div = newDIV(elm, "/clearfix");
    div.style.fontSize = "9pt";
    div.style.marginTop = "10px";
    var dv = newDIV(div, "/left-side");
	dv.style.paddingLeft = "0px";
    var status = vinFilterEnabled(); // localStorage
    var cb = newCHECKBOX(dv, "", "フィルターを有効にする", status);
    cb.setAttribute("onchange", "setVinFilterEnabled(this)"); // localStorage
    var dv = newDIV(div, "/right-side");
	dv.innerHTML = fl_version();
    dv.style.fontSize = "9pt";
    dv.style.color = "#aaa";
    dv.style.paddingRight = "5px";

    // フィルターのリストを表示
    getFiter();
}

function fl_version(){
    return "Ver.131212";
}

// EDITOR ////////////////////////////////////////////
//////////////////////////////////////////////////////


