/*
 * Copyright (C) 2006  Cybozu Labs, Inc.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

if (typeof PlusWiki != "object") {
    var PlusWiki = {};
}

PlusWiki.VERSION = 0.01;

PlusWiki._s = function (n) {
    var s = PlusWiki._string_table[n];
    if (typeof s == 'undefined') {
        s = 'UNKNOWN_STRING_RESOURCE(' + n + ')';
    }
    return s;
};

PlusWiki.init = function (params) {
    
    var required = [ 'backend', 'view' ];
    
    if (typeof params != 'object') {
        alert('argument not an object');
    }
    [ 'backend', 'view' ].each(
        function (n) {
            if (typeof params[n] == 'undefined') {
                alert('no ' + n);
            }
            PlusWiki[n] = params[n];
        });
    
    for (var n in params) {
        if (! required.find(function (i) { return i == n; })
            && typeof PlusWiki[n] != 'undefined') {
            PlusWiki[n] = params[n];
        }
    }
}

PlusWiki.pageName =
    decodeURIComponent(location.search.toQueryParams()['_name'] || 'main');

PlusWiki.editable = true;

PlusWiki.wfParams = {
    nameToLink: function (name) {
        return 'http://' + location.host + location.pathname
            + '?_name=' + name;
    }
};

PlusWiki.newFormatter = function () {
    return new Wiki.Formatter(PlusWiki.wfParams);
};

PlusWiki.wikiView = function () {
    PlusWiki._request(
        'get',
        'view',
        $H({ _name: PlusWiki.pageName }).toQueryString(),
        PlusWiki.onWikiView,
        PlusWiki.onWikiView);
};

PlusWiki.onWikiView = function (json) {
    if (typeof json._error != 'undefined') {
        if (json._error == 'no data') {
            json.text = PlusWiki._s('page_not_found');
        } else {
            alert(json._error);
            return true;
        }
    }
    var formatter = PlusWiki.newFormatter();
    PlusWiki.view.innerHTML = formatter.format(json.text);
    PlusWiki.addController('wiki');
    return true;
};

PlusWiki.editView = function () {
    PlusWiki._request(
        'get',
        'view',
        $H({ _name: PlusWiki.pageName }).toQueryString(),
        PlusWiki.onEditView,
        PlusWiki.onEditView);
};

PlusWiki.onEditView = function (json) {
    if (typeof json._error != 'undefined') {
        if (json._error != 'no data') {
            return false;
        }
        json.text = '';
    }
    PlusWiki.view.innerHTML = [
        '<form onsubmit="return false">',
        '<textarea name="wikisource" cols="80" rows="20">'
            + json.text.escapeHTML()
            + '</textarea>',
        '<br />',
        '<input type="button" value="' + PlusWiki._s('preview') + '" onclick="PlusWiki.onConfirmView({ text: this.form.wikisource.value })" />',
        '<input type="button" value="' + PlusWiki._s('save') + '" onclick="PlusWiki.save({ text: this.form.wikisource.value })" />',
        '<input type="button" value="' + PlusWiki._s('cancel') + '" onclick="PlusWiki.wikiView()" />',
        '</form>'
    ].join('\n');
    PlusWiki.addController('edit');
    return true;
};

PlusWiki.onConfirmView = function (json) {
    var formatter = PlusWiki.newFormatter();
    PlusWiki.view.innerHTML = [
        '<div id="pluswiki-confirm">',
        formatter.format(json.text),
        '</div>',
        '<form onsubmit="return false">',
        '<textarea name="wikisource" cols="80" rows="20" style="display: none;">'
           + json.text.escapeHTML()
           + '</textarea>',
        '<input type="button" value="' + PlusWiki._s('save') + '" onclick="PlusWiki.save({ text: this.form.wikisource.value })" />',
        '<input type="button" value="' + PlusWiki._s('edit') + '" onclick="PlusWiki.onEditView({ text: this.form.wikisource.value })" />',
        '<input type="button" value="' + PlusWiki._s('cancel') + '" onclick="PlusWiki.wikiView()" />',
        '</form>'
    ].join('\n');
    PlusWiki.addController('confirm');
};
    
PlusWiki.historyView = function () {
    PlusWiki._request(
        'get',
        'history',
        $H({ _name: PlusWiki.pageName }).toQueryString(),
        PlusWiki.onHistoryView);
};

PlusWiki.onHistoryView = function (history) {
    var table = [
        '<table width="100%" id="pluswiki-historytable">',
        '<tr>',
        '<th nowrap>' + PlusWiki._s('differences') + '</th>',
        '<th nowrap>' + PlusWiki._s('version') + '</th>',
        '</tr>'
    ];
    for (var i = 0; i < history.length; i++) {
        var h = history[i];
        table.push('<tr>');
        table.push(
            '<td nowrap>'
            + '<input type="radio" name="v1" value="' + h._version + '">'
            + '<input type="radio" name="v2" value="' + h._version + '">'
            + '</td>');
        table.push(
            '<td nowrap>'
            + '<a href="javascript:PlusWiki.oldWikiView(' +
            + h._version
            + ')">' + h._version + '</a>'
            + ' (' + PlusWiki.timeToString(h._mtime) + '; '
            + h._last_editor.escapeHTML()
            + ')</td>');
        table.push('</tr>');
    }
    table.push('</table>');
    PlusWiki.view.innerHTML = [
        '<table width="100%" id="pluswiki-history">',
        '<tr>',
        '<td id="pluswiki-historyrow">',
        '<form onsubmit="PlusWiki.diffView.apply(null, Form.serialize(this).split(\'&\').grep(/^v[12]=/, function (v) { return v.substring(3); }).sort(function (a, b) { return a - b; })); return false">',
        '<h2 class="pluswiki-historyheading">' + PlusWiki._s('history') + ':</h2>',
        '<input type="submit" value="' + PlusWiki._s('show_diff') + '" />',
        table.join('\n'),
        '<input type="submit" value="' + PlusWiki._s('show_diff') + '" />',
        '</form>',
        '</td>',
        '<td valign="top" width="90%" id="pluswiki-historyview"></td>',
        '</tr>',
        '</table>'
    ].join('\n');
    PlusWiki.addController('history');
};

PlusWiki.diffView = function (v1, v2) {
    if (v1 == v2 || typeof v1 == 'undefined' || typeof v2 == 'undefined') {
        alert(PlusWiki._s('diff_noversion'));
        return;
    }
    PlusWiki._request(
        'get',
        'diff',
        $H({ _name: PlusWiki.pageName, v1: v1, v2: v2 }).toQueryString(),
        PlusWiki.onDiffView);
};

PlusWiki.onDiffView = function (diff) {
    $('pluswiki-historyview').innerHTML = [
        '<h2 class="pluswiki-historyheading">',
        PlusWiki._s('differences') + ':',
        '</h2>',
        '<p id="pluswiki-diffheading">',
        PlusWiki._s('diff_from')
             + ': <a href="javascript:PlusWiki.oldWikiView('
             + diff.v1._version + ')">' + diff.v1._version + '</a> ('
             + PlusWiki.timeToString(diff.v1._mtime) + '; '
             + diff.v1._last_editor.escapeHTML()
             + ')',
        '<br />',
        PlusWiki._s('diff_to')
             + ': <a href="javascript:PlusWiki.oldWikiView('
             + diff.v2._version + ')">' + diff.v2._version + '</a> ('
             + PlusWiki.timeToString(diff.v2._mtime) + '; '
             + diff.v2._last_editor.escapeHTML()
             + ')',
        '</p>',
        '<pre id="pluswiki-diffcontent">' + diff.text.escapeHTML() + '</pre>'
    ].join('\n');
};

PlusWiki.oldWikiView = function (ver) {
    PlusWiki._request(
        'get',
        'view',
        $H({ _name: PlusWiki.pageName, _version: ver }).toQueryString(),
        PlusWiki.onOldWikiView);
};

PlusWiki.onOldWikiView = function (json) {
    var formatter = PlusWiki.newFormatter();
    $('pluswiki-historyview').innerHTML = [
        '<h2 class="pluswiki-historyheading">'
            + PlusWiki._s('version')
            + ' '
            + json._version + ':</h2>',
        '<div id="pluswiki-diffcontent">',
        formatter.format(json.text),
        '</div>'
    ].join('\n');
};

PlusWiki.save = function (json) {
    PlusWiki._request(
        'post',
        'save',
        $H({
            _name: PlusWiki.pageName,
            text: json.text.replace(/\r\n/g, '\n')
        }).toQueryString(),
        PlusWiki.wikiView);
};

PlusWiki.addController = function (viewtype) {
    var html = [
        '<div id="pluswiki-controller">',
        '<a href="http://pluswiki.31tools.com/" class="pluswiki-logo">'
            + 'pluswiki</a>:',
        '<a href="javascript:PlusWiki.wikiView()">'
            + PlusWiki._s('view') + '</a>',
        '|',
        PlusWiki.editable ?
            '<a href="javascript:PlusWiki.editView()">'
                + PlusWiki._s('edit') + '</a>' :
            PlusWiki._s('edit'),
        '|',
        '<a href="javascript:PlusWiki.historyView()">'
            + PlusWiki._s('history') + '</a>',
        '</div>'
    ].join('\n');
    PlusWiki.view.innerHTML = html + PlusWiki.view.innerHTML;
};

PlusWiki.connectFunction = function (a, b) {
    return function () {
        a.apply(this, arguments);
        b.apply(this, arguments);
    };
};

PlusWiki.timeToString = function (t) {
    var p = function (v) { return v < 10 ? '0' + v : v; }
    var d = new Date(t * 1000);
    return [d.getFullYear(), p(d.getMonth() + 1), p(d.getDate())].join('/')
        + ' '
        + [p(d.getHours()), p(d.getMinutes())].join(':');
};

PlusWiki._request = function (method, action, params, handler, errorHandler) {
    new Ajax.Request(
        PlusWiki.backend,
        {
            method: method,
            parameters: [
                '__wiki_action=' + action,
                params,
                '_dummy' + new Date().getTime()
            ].join('&'),
            onComplete: function (xhr) {
                var json;
                eval('json = ' + xhr.responseText);
                if (typeof json == 'undefined') {
                    alert('Unexpected response from server\n\n'
                        + xhr.repsonseText);
                } else if (typeof json._error != 'undefined') {
                    if (errorHandler && errorHandler(json)) {
                    } else {
                        alert(json._error);
                    }
                } else {
                    handler(json);
                }
            }
        });
};

