/*
 * HTMLとJavaScriptによる、編集可能なテーブルコンポーネント
 * デフォルト実装
 */
var load = 0;
function defaultInit() {
//    AppUtil.EXECUTION = AppUtil.DEBUGLOG;
    AppUtil.applcationInit();
    var targetTable = document.getElementById("app1_table1");
    var controller = document.getElementById("app1_table1_controller");
    var shell = document.getElementById("app1");
    var view = new DefaultTableView(targetTable, controller);
    var model = new DefaultAppModel();
    view.setModel(model);
    controller.onfocus = function (e) {

//        targetTable.style.border = "thick solid red";
//        AppUtil.printLog("フォーカスが来た");
        HtmlUtil.addClassValue(shell, "onfocus");
        if (0 == load) {
            load = 1;
            return;
        }
        var h2 = document.getElementById("title_001");
        HtmlUtil.scrollTo(h2, 10);
    }
    controller.onblur = function (e) {

//        targetTable.style.outline = "";
//        AppUtil.printLog("フォーカスが行った");
        HtmlUtil.removeClassValue(shell, "onfocus");
    }
    view.invokeFocusToController();
}

/**
 * ここからがテーブルビュー
 */
DefaultTableView.prototype = new TableView();

/**
 * コンストラクタ。
 * @param targetTable : 要素 : Htmlドキュメント上の、テーブル要素
 * @param controller : 要素 : キーボードイベントを受け取る要素
 */
function DefaultTableView(targetTable, controller) {
    if (null == targetTable) {
        return;
    }
    this.initTableView(targetTable, controller);
    this.selectedColumn = 1;
}
/*
 * テーブルの内容が変更されたことを、通知します。
 * TableModelから呼び出される。
 * セル単位の編集可否を、セルのclassに設定する機能を実装。
 * フッタの合計処理を呼び出す機能を追加。
 */
DefaultTableView.prototype.tableChanged = function (tableModelEvent) {

    TableView.prototype.tableChanged.call(this, tableModelEvent);
    /*
     * フッタの合計欄を再表示させる。
     */
    this.setViewValue(99999, 4);
}

/**
 * テーブル表示の初期化を行う。
 * 全体の初期化と、テーブルボディー部以外の内容の表示などを行う。
 * 必ず実装する必要がある。
 */
DefaultTableView.prototype.initializeView = function () {

    if (null != this.model) {

        /*
         * モデルが設定済みの場合は、モデルの行数にテーブルの行数が
         * 足りない場合、その分を追加する。
         */
        var modelRowCount = this.model.getRowCount();
        var bodiesRowCount = this.jsTable.getBodiesRowCount();
        var count = modelRowCount - bodiesRowCount;
        for (var i = 0; i < count; i ++) {
            var row = this.jsTable.getRowFromBodiesAt(0);
            var rowElement = this.jsTable.insertRowAt(-1);
            DomUtil.deepClone2(rowElement, row);
        }
    }

    this.noneDisplayEditor();
    var rows = this.tableElement.rows;

    for (var i = 0; i < rows.length; i ++) {

        var row = rows.item(i);
        HtmlUtil.removeClassValue(row, TableView.selectRowClass);
        HtmlUtil.addClassValue(row, TableView.nonSelectRowClass);

        for (var j = 0; j < row.cells.length; j ++) {

            var cell = row.cells.item(j);
            HtmlUtil.removeClassValue(cell, TableView.selectColumnClass);
            HtmlUtil.addClassValue(cell, TableView.nonSelectColumnClass);
            HtmlUtil.removeClassValue(cell, TableView.editableCellClass);
            HtmlUtil.addClassValue(cell, TableView.nonEditableCellClass);
        }
    }

    if (this.selectedRow == -1) {

        this.selectedRow = 0;
    }
    this.selectRow();
    this.selectColumn();
}

/**
 * 指定セルの入力要素の表示状態を決定する要素を返す。
 * @param rowIndex : 数値 : 行インデックス。
 * @param columnIndex : 数値 : 列インデックス。
 * @return 要素 : 指定のセルの入力要素の表示状態を決定する要素。
 *         該当するセルや入力要素が存在しない場合、null。
 */
DefaultTableView.prototype.getCellEditorViewAt = function (rowIndex, columnIndex) {

    var cellEditor = null;

    var cell = this.getCellAt(rowIndex, columnIndex);
    if (! cell) {

        return null;
    }

    cellEditor = DomUtil.getElementByAttributeValue(cell,
                                                    "className",
                                                    TableView.cellEditorViewClass);

    if (! cellEditor) {

        return null;
    }

    return cellEditor;
}

/*
 * 左矢印キーが押下された。
 * 左側のセルのうち、編集可能なセルを探す機能を追加。
 * 左側に編集可能なセルが存在しない場合、なにもしない。
 */
DefaultTableView.prototype.goLeft = function (evnt) {

    var column = this.selectedColumn - 1;

    if (null != this.model) {

        while (1) {

            if (this.model.isCellEditable(this.selectedRow, column)) {

                break;
            }

            column --;

            if (0 >= column) {

                return;
            }
        }
    }

    this.selectColumnAt(column);
    this.fireSelectionChanged(this.selectedRow, this.selectedColumn);
}

/*
 * 右矢印キーが押下された。
 * 右側のセルのうち、編集可能なセルを探す機能を追加。
 * 右側に編集可能なセルが存在しない場合、なにもしない。
 */
DefaultTableView.prototype.goRight = function (evnt) {

    var column = this.selectedColumn + 1;

    if (null != this.model) {

        var maxColumn = this.model.getColumnCount() == -1 ?
            this.model.getColumnCountAt(this.selectedRow) :
            this.model.getColumnCount();

        while (1) {

            if (this.model.isCellEditable(this.selectedRow, column)) {

                break;
            }

            column ++;

            if (maxColumn <= column) {

                return;
            }
        }
    }

    this.selectColumnAt(column);
    this.fireSelectionChanged(this.selectedRow, this.selectedColumn);
}

/**
 * アプリケーション固有の、セルビュー取得メソッド
 * @param rowIndex : 数値 : 行インデックス。
 * @param columnIndex : 数値 : 列インデックス。
 * @return 要素 : 指定のセルの表示要素。
 *         該当するセルが存在しない場合、null。
 *         デフォルトの表示要素が存在しない場合、セルを返す。
 */
DefaultTableView.prototype.getAppCellValueContainerAt = function (rowIndex, columnIndex) {

    if (99999 != rowIndex) {

        return null;
    }

    return this.jsTable.getCellFromFootAt(0, columnIndex);
}

/**
 * Enterキー押下時の処理
 * ビューを作成する場合、実装が必須。
 */
DefaultTableView.prototype.enter = function () {}


/**
 * テーブルモデル
 */
DefaultAppModel.prototype = new DefaultTableModel();

/**
 * コンストラクタ
 */
function DefaultAppModel() {
    this.initTableModel();
    this.columnCount = 6;
    this.rows = [[0, "20050101", "1000", 1, 0, ""],
                 [0, "20050201", "2000", 2, 0, ""],
                 [0, "20050301",  "500", 3, 0, ""],
                 [0, "20050401", "1234", 4, 0, ""],
                 [0, "20050501",   "80", 5, 0, ""]];
}

/**
 * 指定セルの表示用の値を取得する。
 * 計算処理は、この中で行う。
 * @param rowIndex : 数値 : 値を取得するセルの行インデックス。
 * @param columnIndex : 数値 : 値を取得するセルの列インデックス。
 * @return モデルが格納している値
 */
DefaultAppModel.prototype.getValueAt = function (rowIndex, columnIndex) {

    if (99999 == rowIndex) {

        var total = 0;
        for (var i = 0; i < this.getRowCount(); i ++) {

            var price = this.getEditableValueAt(i, 2);
            var number = this.getEditableValueAt(i, 3);
            total += price * number;
        }
        return this.formatMoney(""+total);
    }

    var value = this.getEditableValueAt(rowIndex, columnIndex);

    if (null == value) {

        return "";
    }

    switch (columnIndex) {
        case 1 :    // 日付

            value = this.formatDate(value);
            break;

        case 2 :    // 単価

            value = this.formatMoney(value);
            break;

        case 4 :    // 合計

            var price = this.getEditableValueAt(rowIndex, 2);
            var number = this.getEditableValueAt(rowIndex, 3);
            value = "" + (price * number);
            value = this.formatMoney(value);
            break;

        case 0 :    // 項番

            value = rowIndex + 1;
            break;

        case 3 :    // 個数
        case 5 :    // 備考
            break;

        default :
    }

    return value;
}

/**
 * 8桁の数字を、日付のフォーマットに変換する。
 * "9999/99/99"
 */
DefaultAppModel.prototype.formatDate = function (value) {

    if (null == value) {

        return "null";
    }

    if (8 != value.length) {

        return value;
    }

    var year = value.slice(0, 4);
    var month = value.slice(4, 6);
    var date = value.slice(6);

    return year+"/"+month+"/"+date;
}

/**
 * 4桁以上の数字に、3桁カンマを挿入する。
 */
DefaultAppModel.prototype.formatMoney = function (value) {

    if (null == value) {

        return "null";
    }

    if (4 > value.length) {

        return value;
    }

    var rtn = "";
    for (var i = 0; i < value.length; i ++) {

        var c = value.charAt((value.length - 1) - i);
        if (0 != i && 0 == i % 3) {
            c += ",";
        }
        rtn = c + rtn;
    }
    return rtn;
}

/**
 * 編集可否判定
 * 指定セルが編集可能かどうかを返す。
 * @param rowIndex : 数値 : 行インデックス。
 * @param columnIndex : 数値 : 列インデックス。
 * @return 必ずtrue
 */
DefaultAppModel.prototype.isCellEditable = function (rowIndex, columnIndex) {

    if (0 == columnIndex || 4 == columnIndex) {

        return false;
    }

    return true;
}

/**
 * 指定のセルの内容が変更されたことを、全てのリスナーに通知する。
 * 計算処理に関係する列が変更された場合は、合計欄も再表示するように指示する。
 * @param rowIndex : 数値 : 値が変更された行インデックス。
 * @param columnIndex : 数値 : 値が変更された列インデックス。
 */
DefaultAppModel.prototype.fireTableCellUpdated = function (rowIndex, columnIndex) {

    var startColumn = columnIndex;
    var endColumn = columnIndex;
    if (2 == columnIndex || 3 == columnIndex) {
        startColumn = 2;
        endColumn = 4;
    }
    var modelEvent = new TableModelEvent(this,
                                         rowIndex,
                                         rowIndex,
                                         startColumn,
                                         endColumn,
                                         TableModelEvent.CELL_UPDATE);

    this.fireTableChanged(modelEvent);
}
