// SelectLayer.tjs - 選択肢レイヤ
// Copyright (C)2001-2006, W.Dee and contributors  改変?配布は自由です

/**
 * 選択肢処理用ボタン
 */
class SelectButtonLayer extends ButtonLayer
{
    var owner; // セレクトレイヤ本体

    var onclick; // クリック時に実行するもの
    var onenter; // マウスが入ってきたときに実行するもの
    var onleave; // マウスが出ていったときに実行するもの
    var storage; // 処理終了後のジャンプ先
    var target;  // 処理終了後のジャンプ先

    /**
     * 文字描画処理に細工
     */
    function drawText(x, y, text, color, opa=255) {
        if (owner.fontEdge) {
            super.drawText(x, y, text, color, opa, true,
                           owner.fontEdgeEmphasis, owner.fontEdgeColor, owner.fontEdgeExtent, 0, 0);
        } else if(owner.fontShadow) {
            super.drawText(x, y, text, color, opa, true,
                           255, owner.fontShadowColor, 0, 2, 2);
        } else {
            super.drawText(x, y, text, color, opa, true);
        }
    }

    /**
     * メッセージの描画
     */
    function drawMessage(message) {
        var cnt = Butt_showFocusImage ? 4 : 3;
        var tw = font.getTextWidth(message);
        var th = font.getTextHeight(message);
        var y = (height-th)>>1;
        //dm("サイズ:" + width + " ," + height);
        var dx = (width-tw)>>1;
        for (var i=0;i<cnt;i++) {
            var x = i*width + dx;
            //dm("メッセージ:" + x);
            drawText(x, y, message, owner.fontColor, 255);
        }
    }
    
    /**
     * コンストラクタ
     * @param owner   選択レイヤ
     * @param message 表示するメッセージを指定
     */
    function SelectButtonLayer(owner, message) {

        this.owner = owner;
        
        // レイヤ初期化
        super.ButtonLayer(owner.window, owner.window.primaryLayer);

        // 文字初期化
        font.face   = owner.fontFace !== void ? owner.fontFace : owner.window.chDefaultFace;
        font.bold   = owner.fontBold;
        font.italic = owner.fontItalic;
        font.height = owner.fontSize;

        if (owner.normalImage !== void) {
            // 画像がある場合はロード
            loadButtons(owner.normalImage, owner.overImage, owner.onImage, owner.focusImage);
            drawMessage(message);
        } else if (owner.graphic !== void) {
            // 画像がある場合はロード
            loadImages(owner.graphic, owner.graphickey);
            drawMessage(message);
        } else {
            // ない場合は組み込みボタンとして処理
            width        = owner.selectWidth;
            height       = owner.selectHeight;
            captionColor = owner.selectColor;
            caption      = message;
        }
    }

    function finalize() {
        super.finalize(...);
	}

	function onMouseEnter()
	{
        if(onenter !== void) Scripts.eval(onenter);
        super.onMouseEnter(...);
        focus();
	}

	function onMouseLeave()
	{
        if(onleave !== void) Scripts.eval(onleave);
        super.onMouseLeave(...);
	}
    
	function onMouseUp(x, y, button, shift)	{
        if (enabled && button == mbLeft) {
            owner.onButtonClick(this);
        }
        if (this isvalid) super.onMouseUp(...);
	}

	function onKeyDown(key, shift, process)
	{
        // キーが押された
        if(window.preProcessKeys(key, shift)) return;
        if (enabled && (key == VK_SPACE || key == VK_RETURN)) {
            owner.onButtonClick(this);
        }
        if (this isvalid) super.onKeyDown(...);
    }

	function onFocus(prevfocused, direction)
	{
        // キー操作によるフォーカス変動の場合にマウスカーソルも移動
        var sgks = window.getKeyState;
        var process = sgks(VK_LEFT) || sgks(VK_UP) || sgks(VK_RIGHT) ||
            sgks(VK_DOWN) || sgks(VK_TAB);
        if(process) {
            cursorX = (width>>1);
            cursorY = (height>>1);
        }
    }
}

/**
 * 選択ボタン取得用
 */
function getSelectButtonLayer(owner, name)
{
    return new SelectButtonLayer(owner, name);
}

/**
 * 選択肢処理用ロジック
 * KAG用に特化しています
 */
class SelectLayer {

    var msgoff = false;
    var fadeTime;
    
    var window;
    
    var left;
    var top;
    var width;
    var height;
    
    // 選択肢項目の属性
    var selectWidth  = 400;
    var selectHeight = 50;
    var selectColor  = 0xffffff;
    var fontSize     = 24;

    // 画像データ
    var graphic;
    var graphickey;
    var normalImage;
    var overImage;
    var onImage;
    var focusImage;

    // フォント
    var fontFace;
    var fontBold;
    var fontItalic;
    var fontShadow;
    var fontEdge;
    var fontColor       = 0xffffff;
    var fontEdgeColor   = 0x0080ff;
    var fontShadowColor = 0000000;
    var fontEdgeEmphasis = 512;
    var fontEdgeExtent = 0;

    // 効果音
    var enterse;
    var leavese;
    var clickse;
    
	function setOptions(elm) {

        // 選択肢領域指定
        left   = +elm.left if elm.left !== void;
        top    = +elm.top  if elm.top  !== void;
        width  = +elm.width if elm.width !== void;
        height = +elm.height if elm.height !== void;
        
        // 画像指定
        normalImage = elm.normal if elm.normal !== void;
        overImage   = elm.over   if elm.over   !== void;
        onImage     = elm.on     if elm.on     !== void;
        focusImage  = elm.focus  if elm.focus  !== void;
        graphic     = elm.graphic    if elm.graphic !== void;
        graphickey  = elm.graphickey if elm.graphickey !== void;

        // サイズ指定
        selectWidth  = +elm.selectWidth  if elm.selectWidth  !== void;
        selectHeight = +elm.selectHeight if elm.selectHeight !== void;

        // フォント指定
        fontFace   = elm.fontFace if elm.fontFace !== void;
        fontSize   = elm.size if elm.size !== void;
        fontColor  = elm.color if elm.color !== void;
        fontItalic = elm.italic if elm.italic !== void;
        fontShadow = elm.shadow if elm.shadow !== void;
        fontEdge   = elm.edge   if elm.edge   !== void;
        fontBold   = elm.bold   if elm.bold   !== void;
        fontEdgeColor = elm.edgeColor     if elm.edgeColor !== void;
        fontShadowColor = elm.shadowColor if elm.shadowColor !== void;

        // 効果音指定
        enterse = elm.enterse if elm.enterse !== void;
        leavese = elm.leavese if elm.leavese !== void;
        clickse = elm.clickse if elm.clickse !== void;

        // メッセージ窓を消去するかどうか
        msgoff = elm.msgoff if elm.msgoff !== void;

        // フェード時間
        fadeTime = +elm.fadetime if elm.fadetime !== void;
    }

    // 登録済み選択肢
    var selects = [];

    /**
     * コンストラクタ
     */
    function SelectLayer(window) {
        this.window = window;
        left   = 0;
        top    = 0;
        width  = window.primaryLayer.width;
        height = window.primaryLayer.height;

        _fadeTimer = new Timer(fadeHandler, '');
        _fadeTimer.capacity = 1;
        _fadeTimer.interval = 10;
        _fadeTimer.enabled  = false;
    }

    function finalize() {
        clearButtons();
        invalidate _fadeTimer;
    }

    /**
     * 不透明度変更処理
     * 関連レイヤもあわせて制御
     */
    function setInnerOpacity(v) {
        if (v !== void) {
            for (var i=0; i<selects.count;i++) {
                var select = selects[i];
                select.opacity = v;
            }
        }
    }

    /**
     * 表示状態変更処理
     * 関連レイヤもあわせて制御
     */
    function setInnerVisible(v) {
        if (v !== void) {
            for (var i=0; i<selects.count;i++) {
                var select = selects[i];
                select.visible = v;
            }
        }
    }

    /**
     * 本来指定されている最終的な表示状態?不透明度にもどして
     * 実行中のフェードを中止する
     */
    function fadeDone() {
        setInnerOpacity(_opacity);
        setInnerVisible(_visible);
        _fadeTimer.enabled = false;
    }
    
    // 不透明度
    var _opacity;
    property opacity {
        setter(v) {
            _opacity = v;
            fadeDone();
        }
        getter() {
            return _opacity;
        }
    }

    // 表示状態
    var _visible = false;
    property visible {
        setter(v) {
            _visible = v;
            fadeDone();
        }
        getter() {
            return _visible;
        }
    }

    var _fadeTimer;
    var _fadeStartTime;
    var _fadeTime;
    var _startOpacity;
    var _fadeDoneFunc;
    
    function fadeHandler() {
        var now = System.getTickCount() - _fadeStartTime;
        if (now >= _fadeTime) {
            fadeDone();
            if (_fadeDoneFunc !== void) {
                _fadeDoneFunc();
            }
        } else {
            setInnerOpacity(_startOpacity + (_opacity - _startOpacity) * now / _fadeTime);
        }
    }

    /**
     * visible に応じてフェードも自動調整する
     */
    function setVisibleTime(v, time, done=void) {
        if (v != visible) {
//            dm("窓フェード表示処理:" + v);
            _visible = v;
            _opacity = v ? 255 : 0;
            if (time > 0) {
                _fadeStartTime = System.getTickCount();
                _fadeTime      = time;
                setInnerOpacity(v ? 0 : 255);
                setInnerVisible(true);
                _startOpacity = v ? 0 : 255;
                _fadeDoneFunc = done;
                _fadeTimer.enabled = true;
            } else {
                fadeDone();
                if (done !== void) {
                    done();
                }
            }
        } 
    }

    /**
     * ボタン消去
     */
    function clearButtons() {
        for (var i=0; i<selects.count;i++) {
            var select = selects[i];
            invalidate select;
        }
        selects.clear();
    }

    /**
     * 選択肢を追加
     */
    function addSelect(elm) {

        var enterse    = elm.enterse !== void ? elm.enterse : enterse;
        var leavese    = elm.leavese !== void ? elm.leavese : leavese;
        var clickse    = elm.clickse !== void ? elm.clickse : clickse;
        var entersebuf = elm.entersebuf !== void ? elm.entersebuf : kag.numSEBuffers - 2;
        var leavesebuf = elm.leavesebuf !== void ? elm.leavesebuf : kag.numSEBuffers - 2;
        var clicksebuf = elm.clicksebuf !== void ? elm.clicksebuf : kag.numSEBuffers - 1;
        
        var select = getSelectButtonLayer(this, elm.text);
        select.name = "选项按钮" + elm.text;
        
        select.onenter = MessageLayer.createSoundExpression(elm.onenter, enterse, entersebuf);
        select.onleave = MessageLayer.createSoundExpression(elm.onleave, leavese, leavesebuf);
        select.onclick = MessageLayer.createSoundExpression(elm.exp,     clickse, clicksebuf),
        select.storage = elm.storage;
        select.target  = elm.target;
        
        selects.add(select);
    }

    /**
     * 選択処理開始
     */
    function start(parent, absolute) {
        var h = height / (selects.count + 1);
        var y = h;
        for (var i=0; i<selects.count;i++) {
            var select = selects[i];
            select.parent   = parent;
            select.absolute = absolute + 4 + i;
            select.setPos(left + width/2 - select.width / 2, top  + y - select.height / 2);
            y += h;
        }
//        dm("フェード時間" + fadeTime);
        if (fadeTime > 0) {
            setVisibleTime(true, fadeTime);
        } else {
            visible = true;
        }
    }

    /**
     * 完了
     */
    function done() {
// 対応めんどいのでとりあえず一瞬消去で対応
//        if (fadeTime !== void) {
//            setVisibleTime(false, fadeTime, clearButtons);
//        } else {
            visible = false;
            clearButtons();
//        }
    }
    
    /**
     * 処理終了
     */
    function onButtonClick(select) {
        if (select !== void) {
            Scripts.eval(select.onclick) if select.onclick != '';
            if (select isvalid) {
                if (select.storage != '' || select.target != '')	{
                    window.process(select.storage, select.target);
                } else {
                    window.processGo();
                }
                window.doneSelect();
            }
        }
    }

	var invisibleByUser = false; // ユーザにより一時的に不可視
	var visibleBeforeUserInvisible  = false;

    function setHiddenStateByUser(b)
	{
        // ユーザが右クリックなどでメッセージレイヤを一時的に隠すときに
		// 呼ばれる
		if(b)
		{
			visibleBeforeUserInvisible = visible;
			invisibleByUser = true; // ユーザにより一時的に不可視
			visible = false;
		}
		else
		{
			invisibleByUser = false; // 可視
			visible = visibleBeforeUserInvisible;
		}
	}

    function lockFocus() {
        for (var i=0; i<selects.count;i++) {
            var select = selects[i];
            select.focusable = false;
        }
    }
    
    function unlockFocus() {
        for (var i=0; i<selects.count;i++) {
            var select = selects[i];
            select.focusable = true;
        }
    }
}
