(function() {
var shovel = window.shovel || {};

$.extend(shovel, {
    trim: function(text) {
        return text.replace(/^\s+|\s+$/g, '');
    },
    unrtf: function(template) {
        template = template.replace(/\\\\/g, '\\');
        template = template.replace(/\\{/g, '{');
        return template.replace(/\\}/g, '}');
    },
    init: function() {
        var self = this;
        $.ajaxSetup({
            error: self.showError,
            beforeSend: function(xml) {
                self.beforeSend(xml);
            }
        });
    },
    getMessage: function(key) {
        if (!this.resources) {
            var resources = $('#javascript_resources').val();
            this.resources = eval('(' + resources + ')');
        }
        var args = {};
        if (arguments.length > 1) {
            for (var i = 1, j = 0; i < arguments.length; i++, j++) {
                args['arg' + j] = arguments[i];
            }
        }
        return this.resources[key].process(args);
    },
    showAjaxError: function(event, request, settings) {
        $('#loader').css('display', 'none');
        if (arguments.length > 1) {
            msg = $('#template_ajaxError').val();
        }
        var closeHandler = function() {
            this.hide();
        };
        var dialog = new YAHOO.widget.SimpleDialog('error', {
            width: '320px',
            fixedcenter: true,
            visible: false,
            draggable: false,
            modal: true,
            close: true,
            text: msg,
            icon: YAHOO.widget.SimpleDialog.ICON_WARN,
            constraintoviewport: true,
            buttons: [
                {text: shovel.getMessage('button.close'),
                 handler: closeHandler,
                 isDefault: true}
            ]
        });
        dialog.render(document.body)
        dialog.show();
    },
    showApplicationError: function(json) {
        $('#loader').css('display', 'none');
        var args = eval('(' + json + ')');
        var html = $('#template_applicationError').val().process(args);
        $('.content').html(html);
    },
    flashWarn: function(flash, msg) {
        var html = $('#template_flash').val().process({msg: msg});
        $(flash).html(html);
        $(flash).css('display', '');

        setTimeout(function() {
            $(flash).slideUp(750, function() {
                $(flash).empty();
            });
        }, 2000);
    },
    splitResponseByBoundary: function() {
        var boundary = this._xml.getResponseHeader('X-Response-Boundary');
        return this.splitTextByBoundary(this._xml.responseText, boundary);
    },
    splitTextByBoundary : function(text, boundary) {
        return text.split(boundary);
    },
    beforeSend: function(xml) {
        this._xml = xml;
    },
    //Model
    Status: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    DirectMessage: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    Friendship: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    Account: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    System: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    //View
    AccountView: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    FavoritesView: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    FriendsView: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    HomeView: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    DirectMessagesView: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    PeopleView: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    RootView: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    ShowStatusView: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    SystemView: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    SearchUsersView: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    FriendRequestsView: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    //Controller
    AccountController: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    FavoritesController: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    FriendsController: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    HomeController: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    DirectMessagesController: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    PeopleController: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    RootController: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    ShowStatusController: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    SystemController: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    SearchUsersController: function(controllerInfo) {
        this.constructor(controllerInfo);
    },
    FriendRequestsController: function(controllerInfo) {
        this.constructor(controllerInfo);
    }
});
shovel.Status.prototype = {
    constructor: function(controllerInfo) {
        this._urlMap = controllerInfo.urlMap;
        this._idMap = controllerInfo.idMap;
    },
    updateStatus: function(callback) {
        var status = shovel.trim($(this._idMap.status).val());
        if (status.length <= 0) {
            msg = shovel.getMessage('warning.emptyStatus');
            shovel.flashWarn(this._idMap.flash, msg);
            return;
        }
        var self = this;
        var callbackWrapper = function(json, status) {
            var msg;
            switch (json.type) {
            case 'directMessage':
               msg = shovel.getMessage('notify.directMessage', json.foreignKey);
               break;
            case 'favorite':
               msg = shovel.getMessage('notify.favorite', json.foreignKey);
               break;
            case 'friendRequest':
               msg = shovel.getMessage('notify.friendRequest', json.foreignKey);
               break;
            case 'follow':
               msg = shovel.getMessage('notify.follow', json.foreignKey);
               break;
            case 'leave':
               msg = shovel.getMessage('notify.leave', json.foreignKey);
               break;
            case 'notifyOn':
               msg = shovel.getMessage('notify.notifyOn', json.foreignKey);
               break;
            case 'notifyOff':
               msg = shovel.getMessage('notify.notifyOff', json.foreignKey);

               break;
            default:
            case 'status':
                msg = shovel.getMessage('notify.update');
                if ($(self._idMap.status).val().length > 140) {
                    msg = shovel.getMessage('warning.overStatus');
                }
                break;
            }
            
            shovel.flashWarn(self._idMap.flash, msg);
            callback(json, status);
        }
        var url = this._urlMap.updateStatus;
        var params = $(this._idMap.form).serialize();
        $.post(url, params, callbackWrapper, 'json');
    },
    replyStatus: function(statusId) {
        var foreignKey = $(this._idMap.foreignKey + statusId).html();
        var content = $(this._idMap.status).val();
        if (content && content.length > 0) {
            content += ' ';
        }
        $(this._idMap.status).val(content + '@' + foreignKey + ' ');
    },
    getStatuses: function(callback) {
        $(this._idMap.partial).val(true);
        var viewID = $(this._idMap.viewID).val();
        var url = this._urlMap[viewID];
        var params = $(this._idMap.form).serialize();
        $.post(url, params, callback);
    },
    getStatusesByPage: function(page, viewID, callback) {
        $(this._idMap.page).val(page);
        $(this._idMap.method).val('page');
        if (viewID) {
            $(this._idMap.viewID).val(viewID);
        }
        this.getStatuses(callback);
    },
    destroyStatus: function(statusId, callback) {
        var msg = shovel.unrtf($('#template_destroyStatus').val()).process({
            'status': $(this._idMap.status + '_' + statusId).html()
        });
        var self = this;
        var yesHandler = function() {
            var url = self._urlMap.destroyStatus + statusId;
            var params = $(self._idMap.form).serialize();
            var self2 = this;
            var callbackWrapper = function(html, status) {
                callback(html, status);
                self2.hide();
            }
            $.post(url, params, callbackWrapper);
        };
        var noHandler = function() {
            this.hide();
        };
        var dialog = new YAHOO.widget.SimpleDialog('error', {
            width: '320px',
            fixedcenter: true,
            visible: false,
            draggable: false,
            modal: true,
            close: true,
            text: msg,
            icon: YAHOO.widget.SimpleDialog.ICON_WARN,
            constraintoviewport: true,
            buttons: [
                {text: shovel.getMessage('button.delete'), handler: yesHandler, isDefault:true},
                {text: shovel.getMessage('button.cancel'), handler: noHandler}
            ]
        });
        dialog.render(document.body)
        dialog.show();
    },
    setFavorite: function(statusId, callback) {
        $(this._idMap.partial).val(true);
        var url = this._urlMap.setFavorite + statusId;
        var params = $(this._idMap.form).serialize();
        $.post(url, params, callback);
    },
    unsetFavorite: function(statusId, callback) {
        $(this._idMap.partial).val(true);
        var url = this._urlMap.unsetFavorite + statusId;
        var params = $(this._idMap.form).serialize();
       $.post(url, params, callback);
    }
}
shovel.DirectMessage.prototype = {
    constructor: function(controllerInfo) {
        this._urlMap = controllerInfo.urlMap;
        this._idMap = controllerInfo.idMap;
    },
    getDirectMessages: function(callback) {
        $(this._idMap.partial).val(true);
        var viewID = $(this._idMap.viewID).val();
        var url = this._urlMap[viewID];
        var params = $(this._idMap.form).serialize();
        $.post(url, params, callback);
    },
    getDirectMessagesByPage: function(page, viewID, callback) {
        $(this._idMap.page).val(page);
        $(this._idMap.method).val("page");
        if (viewID) {
            $(this._idMap.viewID).val(viewID);
        }
        this.getDirectMessages(callback);
    },
    createDirectMessage: function(callback) {
        var self = this;
        var callbackWrapper = function(html, status) {
            if ($(self._idMap.text).val().length > 140) {
                var msg = shovel.getMessage('warning.overStatus');
            }
            var msg = shovel.getMessage('notify.update');
            shovel.flashWarn(self._idMap.flash, msg);
            callback(html, status);
        }
        var url = this._urlMap.createDirectMessage;
        var params = $(this._idMap.form).serialize();
        $.post(url, params, callbackWrapper);
    },
    replyDirectMessage: function(foreignKey) {
        var recipient = $('#directMessages_recipient');
        if (!recipient.attr('disabled')) {
            var recipients = $('#directMessages_recipient option');
            recipients.each(function() {
                if ($(this).val() == foreignKey) {
                    $(this).attr('selected', 'selected');
                    return false;
                }
            });
        }
    },
    destroyDirectMessage: function(directMessageId, callback) {
        var msg = shovel.unrtf($('#template_destroyDirectMessage').val()).process({
            'text': $(this._idMap.text + '_' + directMessageId).html()
        });
        var self = this;
        var yesHandler = function() {
            var url = self._urlMap.destroyDirectMessage + directMessageId;
            var params = $(self._idMap.form).serialize();
            var self2 = this;
            var callbackWrapper = function(html, status) {
                callback(html, status);
                self2.hide();
            }
            $.post(url, params, callbackWrapper);
        };
        var noHandler = function() {
            this.hide();
        };
        var dialog = new YAHOO.widget.SimpleDialog('error', {
            width: '320px',
            fixedcenter: true,
            visible: false,
            draggable: false,
            modal: true,
            close: true,
            text: msg,
            icon: YAHOO.widget.SimpleDialog.ICON_WARN,
            constraintoviewport: true,
            buttons: [
                {text: shovel.getMessage('button.delete'), handler: yesHandler, isDefault:true},
                {text: shovel.getMessage('button.cancel'), handler: noHandler}
            ]
        });
        dialog.render(document.body)
        dialog.show();
    }
}
shovel.Friendship.prototype = {
    constructor: function(controllerInfo) {
        this._statusId = controllerInfo.statusId;
        this._urlMap = controllerInfo.urlMap;
        this._idMap = controllerInfo.idMap;
    },
    getFriendships: function(callback) {
        $(this._idMap.partial).val(true);
        var viewID = $(this._idMap.viewID).val();
        var url = this._urlMap[viewID];
        var params = $(this._idMap.form).serialize();
        $.post(url, params, callback);
    },
    getFriendshipsByPage: function(page, callback) {
        $(this._idMap.page).val(page);
        $(this._idMap.method).val("page");
        this.getFriendships(callback);
    },
    createFriendship: function(callback, foreignKey) {
        var url = this._urlMap.createFriendship;
        if (foreignKey) {
            url = this._urlMap.friendship + '/create/' + foreignKey;
        } else {
            foreignKey = $(this._idMap.foreignKey).val();
        }
        var self = this;
        var callbackWrapper = function(html, status) {
            var protect = $(self._idMap.protect).val();
            if (eval(protect)) {
                var msg = shovel.getMessage('notify.friendRequest', foreignKey);
                shovel.flashWarn(self._idMap.flash, msg);
            }
            callback(html, status);
        }
        $.post(url, '', callbackWrapper);
    },
    destroyFriendship: function(callback, foreignKey) {
        var url = this._urlMap.destroyFriendship;
        if (foreignKey) {
            url = this._urlMap.friendship + '/destroy/' + foreignKey;
        }
        $.post(url, '', callback);
    },
    getFriendRequests: function(callback) {
        $(this._idMap.partial).val(true);
        var viewID = $(this._idMap.viewID).val();
        var url = this._urlMap[viewID];
        var params = $(this._idMap.form).serialize();
        $.post(url, params, callback);
    },
    acceptFriendRequest: function(foreignKey, callback) {
        var url = this._urlMap.acceptFriendRequest + foreignKey;
        $.post(url, '', callback);
    },
    denyFriendRequest: function(foreignKey, callback) {
        var url = this._urlMap.denyFriendRequest + foreignKey;
        $.post(url, '', callback);
    },
    setNotify: function(foreignKey) {
        var url = this._urlMap.friendship + '/follow';
        if (foreignKey) {
            url += '/' + foreignKey;
        }
        $.post(url, '');
    },
    unsetNotify: function(foreignKey) {
        var url = this._urlMap.friendship + '/leave';
        if (foreignKey) {
            url += '/' + foreignKey;
        }
        $.post(url, '');
    }
};
shovel.Account.prototype = {
    constructor: function(controllerInfo) {
        this._urlMap = controllerInfo.urlMap;
        this._idMap = controllerInfo.idMap;
    },
    changeConfig: function(type, callback) {
        var url = this._urlMap.changeConfig;
        url += type;
        var params = $(this._idMap.form).serialize();
        $.get(url, params, callback);
    },
    updateSettings: function(callback) {
        var url = this._urlMap.settings;
        var params = $(this._idMap.form).serialize();
        $.post(url, params, callback);
    },
    updateUser: function(callback) {
        var url = this._urlMap.updateUser;
        var params = $(this._idMap.usersForm).serialize();
        $.post(url, params, callback);
    },
    importAccounts: function() {
        var form = $(this._idMap.form);
        //IEだとなぜかエラー、元がPOSTだからいいか。。
//        form.attr('method', 'post');
        form.attr('action', this._urlMap.importAccounts);
        form.attr('target', 'fileUpload');
        if ($.browser.msie) {
            form.attr('encoding', 'multipart/form-data');
        } else {
            form.attr('enctype', 'multipart/form-data');
        }
        form.submit();
        return false;
    },
    updateNotices: function(callback) {
        var url = this._urlMap.notices;
        var params = $(this._idMap.form).serialize();
        $.post(url, params, callback);
    },
    updatePicture: function() {
        var form = $(this._idMap.form);
        form.attr('method', 'post');
        form.attr('action', this._urlMap.picture);
        form.attr('target', 'fileUpload');
        if ($.browser.msie) {
            form.attr('encoding', 'multipart/form-data');
        } else {
            form.attr('enctype', 'multipart/form-data');
        }
        form.submit();
        return false;
    },
    updateDesign: function() {
        var form = $(this._idMap.form);
        form.attr('method', 'post');
        form.attr('action', this._urlMap.design);
        form.attr('target', 'fileUpload');
        if ($.browser.msie) {
            form.attr('encoding', 'multipart/form-data');
        } else {
            form.attr('enctype', 'multipart/form-data');
        }
        form.submit();
        return false;
    },
    resendPassword: function() {
        var form = $(this._idMap.form);
        form.attr('method', 'post');
        form.attr('action', this._urlMap.resendPassword);
        form.submit();
        return false;
    },
    resetPassword: function() {
        var password = $(this._idMap.password).val();
        var confirmation = $(this._idMap.confirmation).val();
        if (password != confirmation) {
            return false;
        }
        var form = $(this._idMap.form);
        form.attr('method', 'post');
        form.attr('action', this._urlMap.resetPassword);
        form.submit();
        return true;
    },
    destroyPicture: function(callback) {
        var destroy = $(this._idMap.destroyPicture).attr('checked');
        callback(destroy);
    },
    changePassword: function(callback) {
        var password = $(this._idMap.password).val();
        var confirmation = $(this._idMap.confirmation).val();
        if (password != confirmation) {
            return false;
        }
        var url = this._urlMap.password;
        var params = $(this._idMap.form).serialize();
        $.post(url, params, callback);
        return true;
    },
    conflictForeignKey: function(callback) {
        var foreignKey = $(this._idMap.foreignKey).val();
        var match = foreignKey.match(/^[\w-\.\-]+$/);
        if (foreignKey != match) {
            callback({invalid: true});
            return;
        }
        var url = this._urlMap.conflictForeignKey;
        var params = $(this._idMap.form).serialize();
        $.post(url, params, callback, 'json');
    },
    registerDevice: function(callback) {
        $(this._idMap.phase).val(0);
        var url = this._urlMap.device;
        var params = $(this._idMap.form).serialize();
        $.post(url, params, callback, 'json');
    },
    freshDevice: function(callback) {
        $(this._idMap.phase).val(1);
        var url = this._urlMap.device;
        var params = $(this._idMap.form).serialize();
        $.post(url, params, callback, 'json');
    },
    updateDevice: function(form, callback) {
        $(this._idMap.phase).val(2);
        var url = this._urlMap.device;
        if (!form) {
            form = this._idMap.form;
        }
        var params = $(form).serialize();
        $.post(url, params, callback, 'json');
    },
    testSubmit: function(json, callback) {
        var displayName = $(this._idMap.displayName).val();
        var foreignKey = $(this._idMap.foreignKey).val();
        var conflictForeignKey;
        if (json) {
            conflictForeignKey = !json.already && !json.invalid;
        } else {
            //うーん。。
            conflictForeignKey = $(this._idMap.url).css('color') == 'green';
        }
        callback(displayName.length > 0 && foreignKey.length > 0 && conflictForeignKey);
    },
    getUsers: function(callback) {
        $(this._idMap.partial).val(true);
        var url = this._urlMap.accounts;
        var params = $(this._idMap.form).serialize();
        $.get(url, params, callback);
    },
    getUsersByPage: function(page, callback) {
        $(this._idMap.page).val(page);
        $(this._idMap.method).val('page');
        this.getUsers(callback);
    },
    getUsersBySort: function(desc, callback) {
        $(this._idMap.sortOrder).val(desc ? 'desc' : 'asc');
        $(this._idMap.method).val('sortOrder');
        this.getUsers(callback);
    },
    searchUsers: function(callback) {
        $(this._idMap.partial).val(true);
        var viewID = $(this._idMap.viewID).val();
        var url = this._urlMap[viewID];
        var params = $(this._idMap.form).serialize();
        $.post(url, params, callback);
    },
    searchUsersByPage: function(page, callback) {
        $(this._idMap.page).val(page);
        $(this._idMap.method).val('page');
        this.searchUsers(callback);
    },
    destroyAccounts: function(callback) {
        var users = $('input:checked');
        var userCount = users.length;
        var msg, userId;
        if (userCount > 1) {
            msg = shovel.unrtf($('#template_destroyAccounts').val()).process({
                userCount: userCount
            });
        } else {
            userId = $(users.get()).val();
            msg = shovel.unrtf($('#template_destroyAccounts').val()).process({
                userCount: 1,
                displayName: $(this._idMap.displayName + '_' + userId).html(),
                foreignKey: $(this._idMap.foreignKey + '_' + userId).html()
            });
        }
        var self = this;
        var yesHandler = function() {
            var url = self._urlMap.destroyAccounts;
            var params = '';
            if (userCount > 1) {
                params = $(self._idMap.form).serialize();
            } else {
                url += '/' + userId;
            }
            var self2 = this;
            var callbackWrapper = function(html, status) {
                callback(html, status);
                self2.hide();
            }
            $.post(url, params, callbackWrapper);
        };
        var noHandler = function() {
            this.hide();
        };
        var dialog = new YAHOO.widget.SimpleDialog('error', {
            width: '320px',
            fixedcenter: true,
            visible: false,
            draggable: false,
            modal: true,
            close: true,
            text: msg,
            icon: YAHOO.widget.SimpleDialog.ICON_WARN,
            constraintoviewport: true,
            buttons: [
                {text: shovel.getMessage('button.delete'), handler: yesHandler, isDefault:true},
                {text: shovel.getMessage('button.cancel'), handler: noHandler}
            ]
        });
        dialog.render(document.body)
        dialog.show();
    },
    toggleAllAccount: function() {
        var accounts = $(this._idMap.userIds);
        var checked = accounts.filter(':checked');
        if (checked.length > 0) {
            accounts = checked;
        }
        accounts.each(function() {
            if (!$(this).attr('disabled')) {
                $(this).attr('checked', !$(this).attr('checked'));
            }
        });
        this.toggleAccount();
    },
    toggleAccount: function() {
        var disabled = $(this._idMap.userIds + ':checked').length <= 0;
        $(this._idMap.destroyAccounts).attr('disabled', disabled);
    },
    destroyBackground: function(callback) {
        var destroy = $(this._idMap.destroyBackground).attr('checked');
        callback(destroy);
    }
};
shovel.RootController.prototype = {
    constructor: function(controllerInfo) {
        controllerInfo.controller = this;
        this._idMap = controllerInfo.idMap;
        this._view = new shovel.RootView(controllerInfo);
    },
    focusKeyword: function() {
        this._view.focusKeyword();
    },
    blurKeyword: function() {
        this._view.blurKeyword();
    },
    focusPassword: function() {
        this._view.focusPassword();
    },
    blurPassword: function() {
        this._view.blurPassword();
    },
    focusUsername: function() {
        this._view.focusUsername();
    },
    blurUsername: function() {
        this._view.blurUsername();
    },
    searchUsers: function(event) {
        if (event) {
            if (event.keyCode) {
                if (event.keyCode != 13) {
                    return;
                }
            } else if (event.charCode) {
                if (event.charCode != 13) {
                    return;
                }
            } else {
                return;
            }
            $(this._idMap.inputed).val(true);
        }
        if (!eval($(this._idMap.inputed).val())) {
            $(this._idMap.keyword).val('');
        } else {
            var keyword = $(this._idMap.inputKeyword).val();
            keyword = shovel.trim(keyword);
            $(this._idMap.keyword).val(keyword);
        }
        $(this._idMap.searchForm).submit();
    }
}
shovel.HomeController.prototype = {
    constructor: function(controllerInfo) {
        controllerInfo.controller = this;
        this._idMap = controllerInfo.idMap;
        this._status = new shovel.Status(controllerInfo);
        this._account = new shovel.Account(controllerInfo);
        this._view = new shovel.HomeView(controllerInfo);
    },
    getStatuses: function() {
        var self = this;
        var callback = function(html, status) {
            self._view.render(html, status);
        };
        this._status.getStatuses(callback);
        return false;
    },
    getStatusesByPage: function(page, contentEl) {
        var self = this;
        var callback = function(html, status) {
            self._view.render(html, status, contentEl);
        };
        this._status.getStatusesByPage(page, contentEl, callback);
        return false;
    },
    updateStatus: function() {
        var self = this;
        var callback = function(html, status) {
            self.getStatuses();
            self._view.clearStatus();
        };
        this._status.updateStatus(callback);
        return false;
    },
    replyStatus: function(statusId) {
        this._status.replyStatus(statusId);
        return false;
    },
    destroyStatus: function(statusId) {
        var self = this;
        var callback = function(html, status) {
            self.getStatuses();
        };
        this._status.destroyStatus(statusId, callback);
        return false;
    },
    focusInputStatus: function() {
        this._view.focusInputStatus();
    },
    blurInputStatus: function() {
        this._view.blurInputStatus();
    },
    focusStatus: function(statusId) {
        this._view.focusStatus(statusId);
    },
    blurStatus: function(statusId) {
        this._view.blurStatus(statusId);
    },
    setFavorite: function(statusId) {
        var self = this;
        var callback = function() {
            self._view.setFavorite(statusId);
        }
        this._view.settingFavorite(statusId);
        this._status.setFavorite(statusId, callback);
        return false;
    },
    unsetFavorite: function(statusId) {
        var self = this;
        var callback = function() {
            self._view.unsetFavorite(statusId);
        }
        this._view.settingFavorite(statusId);
        this._status.unsetFavorite(statusId, callback);
        return false;
    },
    switchView: function(viewID) {
        this._view.switchView(viewID);
        return false;
    },
    updateDevice: function() {
        var self = this;
        this._account.updateDevice(this._idMap.sidebarForm);
        return false;
    },
    focusKeyword: function() {
        this._view.focusKeyword();
    },
    blurKeyword: function() {
        this._view.blurKeyword();
    },
    searchUsers: function(event) {
        if (event) {
            if (event.keyCode) {
                if (event.keyCode != 13) {
                    return;
                }
            } else if (event.charCode) {
                if (event.charCode != 13) {
                    return;
                }
            } else {
                return;
            }
            $(this._idMap.inputed).val(true);
        }
        if (!eval($(this._idMap.inputed).val())) {
            $(this._idMap.keyword).val('');
        } else {
            var keyword = $(this._idMap.inputKeyword).val();
            keyword = shovel.trim(keyword);
            $(this._idMap.keyword).val(keyword);
        }
        $(this._idMap.searchForm).submit();
    }
};
shovel.DirectMessagesController.prototype = {
    constructor: function(controllerInfo) {
        controllerInfo.controller = this;
        this._idMap = controllerInfo.idMap;
        this._urlMap = controllerInfo.urlMap;
        this._account = new shovel.Account(controllerInfo);
        this._directMessage = new shovel.DirectMessage(controllerInfo);
        this._view = new shovel.DirectMessagesView(controllerInfo);
    },
    getDirectMessages: function() {
        var self = this;
        var callback = function(html, status) {
            self._view.render(html, status);
        };
        this._directMessage.getDirectMessages(callback);
        return false;
    },
    getDirectMessagesByPage: function(page, contentEl) {
        var self = this;
        var callback = function(html, status) {
            self._view.render(html, status, contentEl);
        };
        this._directMessage.getDirectMessagesByPage(page, contentEl, callback);
        return false;
    },
    createDirectMessage: function() {
        var self = this;
        var callback = function(html, status) {
            if ($('#directMessages_specified').val()) {
                location.href = self._urlMap.sent;
            } else {
                self.getDirectMessages();
                self._view.clearDirectMessage();
            }
        };
        this._directMessage.createDirectMessage(callback);
        return false;
    },
    replyDirectMessage: function(foreignKey) {
        this._directMessage.replyDirectMessage(foreignKey);
        return false;
    },
    destroyDirectMessage: function(directMessageId) {
        var self = this;
        var callback = function(html, status) {
            self.getDirectMessages();
        };
        this._directMessage.destroyDirectMessage(directMessageId, callback);
        return false;
    },
    focusInputDirectMessage: function() {
        this._view.focusInputDirectMessage();
    },
    blurInputDirectMessage: function() {
        this._view.blurInputDirectMessage();
    },
    focusDirectMessage: function(directMessageId) {
        this._view.focusDirectMessage(directMessageId);
    },
    blurDirectMessage: function(directMessageId) {
        this._view.blurDirectMessage(directMessageId);
    },
    updateDevice: function() {
        var self = this;
        this._account.updateDevice(this._idMap.sidebarForm);
        return false;
    },
    focusKeyword: function() {
        this._view.focusKeyword();
    },
    blurKeyword: function() {
        this._view.blurKeyword();
    },
    searchUsers: function(event) {
        if (event) {
            if (event.keyCode) {
                if (event.keyCode != 13) {
                    return;
                }
            } else if (event.charCode) {
                if (event.charCode != 13) {
                    return;
                }
            } else {
                return;
            }
            $(this._idMap.inputed).val(true);
        }
        if (!eval($(this._idMap.inputed).val())) {
            $(this._idMap.keyword).val('');
        } else {
            var keyword = $(this._idMap.inputKeyword).val();
            keyword = shovel.trim(keyword);
            $(this._idMap.keyword).val(keyword);
        }
        $(this._idMap.searchForm).submit();
    }
};
shovel.PeopleController.prototype = {
    constructor: function(controllerInfo) {
        this._idMap = controllerInfo.idMap;
        this._status = new shovel.Status(controllerInfo);
        this._friendship = new shovel.Friendship(controllerInfo);
        this._view = new shovel.PeopleView(controllerInfo);
    },
    createFriendship: function() {
        var self = this;
        var callback = function(html, status) {
            self._view.createFriendship();
        }
        this._friendship.createFriendship(callback);
        return false;
    },
    destroyFriendship: function() {
        var self = this;
        var callback = function(html, status) {
            self._view.destroyFriendship();
        }
        this._friendship.destroyFriendship(callback);
        return false;
    },
    acceptFriendRequest: function(foreignKey) {
        var self = this;
        var callback = function(html, status) {
            self._view.acceptFriendRequest();
        }
        this._friendship.acceptFriendRequest(foreignKey, callback);
    },
    denyFriendRequest: function(foreignKey) {
        var self = this;
        var callback = function(html, status) {
            self._view.denyFriendRequest(); 
        }
        this._friendship.denyFriendRequest(foreignKey, callback);
    },
    getStatuses: function() {
        var self = this;
        var callback = function(html, status) {
            self._view.render(html, status);
        };
        this._status.getStatuses(callback);
        return false;
    },
    getStatusesByPage: function(page, contentEl) {
        var self = this;
        var callback = function(html, status) {
            self._view.render(html, status, contentEl);
        };
        this._status.getStatusesByPage(page, contentEl, callback);
        return false;
    },
    destroyStatus: function(statusId) {
        var self = this;
        var callback = function(html, status) {
            self.getStatuses();
        };
        this._status.destroyStatus(statusId, callback);
        return false;
    },
    focusStatus: function(statusId) {
        //$('#people_action_' + statusId).css('display', '');
        $('#people_favorite_' + statusId).css('display', '');
        $('#people_destroyStatus_' + statusId).css('display', '');
        $('#people_replyStatus_' + statusId).css('display', '');
    },
    blurStatus: function(statusId) {
        //$('#people_action_' + statusId).css('display', 'none');
        var fav = $('#people_favorite_' + statusId);
        if (!fav.hasClass('favorite')) {
            fav.css('display', 'none');
        }
        $('#people_destroyStatus_' + statusId).css('display', 'none');
        $('#people_replyStatus_' + statusId).css('display', 'none');
    },
    setFavorite: function(statusId) {
        var self = this;
        var callback = function() {
            self._view.setFavorite(statusId);
        }
        this._view.settingFavorite(statusId);
        this._status.setFavorite(statusId, callback);
        return false;
    },
    unsetFavorite: function(statusId) {
        var self = this;
        var callback = function() {
            self._view.unsetFavorite(statusId);
        }
        this._view.settingFavorite(statusId);
        this._status.unsetFavorite(statusId, callback);
        return false;
    },
    focusKeyword: function() {
        this._view.focusKeyword();
    },
    blurKeyword: function() {
        this._view.blurKeyword();
    },
    searchUsers: function(event) {
        if (event) {
            if (event.keyCode) {
                if (event.keyCode != 13) {
                    return;
                }
            } else if (event.charCode) {
                if (event.charCode != 13) {
                    return;
                }
            } else {
                return;
            }
            $(this._idMap.inputed).val(true);
        }
        if (!eval($(this._idMap.inputed).val())) {
            $(this._idMap.keyword).val('');
        } else {
            var keyword = $(this._idMap.inputKeyword).val();
            keyword = shovel.trim(keyword);
            $(this._idMap.keyword).val(keyword);
        }
        $(this._idMap.searchForm).submit();
    }
};
shovel.FavoritesController.prototype = {
    constructor: function(controllerInfo) {
        controllerInfo.controller = this;
        this._idMap = controllerInfo.idMap;
        this._friendship = new shovel.Friendship(controllerInfo);
        this._status = new shovel.Status(controllerInfo);
        this._view = new shovel.FavoritesView(controllerInfo);
    },
    createFriendship: function() {
        var self = this;
        var callback = function(html, status) {
            self._view.createFriendship();
        }
        this._friendship.createFriendship(callback);
        return false;
    },
    destroyFriendship: function() {
        var self = this;
        var callback = function(html, status) {
            self._view.destroyFriendship();
        }
        this._friendship.destroyFriendship(callback);
        return false;
    },
    acceptFriendRequest: function(foreignKey) {
        var self = this;
        var callback = function(html, status) {
            self._view.acceptFriendRequest();
        }
        this._friendship.acceptFriendRequest(foreignKey, callback);
    },
    denyFriendRequest: function(foreignKey) {
        var self = this;
        var callback = function(html, status) {
            self._view.denyFriendRequest(); 
        }
        this._friendship.denyFriendRequest(foreignKey, callback);
    },
    getStatuses: function() {
        var self = this;
        var callback = function(html, status) {
            self._view.render(html, status);
        };
        this._status.getStatuses(callback);
        return false;
    },
    getStatusesByPage: function(page) {
        var self = this;
        var callback = function(html, status) {
            self._view.render(html, status);
        };
        this._status.getStatusesByPage(page, null, callback);
        return false;
    },
    destroyStatus: function(statusId) {
        var self = this;
        var callback = function(html, status) {
            self.getStatuses();
        };
        this._status.destroyStatus(statusId, callback);
        return false;
    },
    focusStatus: function(statusId) {
        //$('#home_status_action_' + statusId).css('display', '');
        $('#home_favorite_' + statusId).css('display', '');
        $('#home_destroyStatus_' + statusId).css('display', '');
        $('#home_replyStatus_' + statusId).css('display', '');
    },
    blurStatus: function(statusId) {
        //$('#home_status_action_' + statusId).css('display', 'none');
        var fav = $('#home_favorite_' + statusId);
        if (!fav.hasClass('favorite')) {
            fav.css('display', 'none');
        }
        $('#home_destroyStatus_' + statusId).css('display', 'none');
        $('#home_replyStatus_' + statusId).css('display', 'none');
    },
    setFavorite: function(statusId) {
        var self = this;
        var callback = function() {
            self._view.setFavorite(statusId);
        }
        this._view.settingFavorite(statusId);
        this._status.setFavorite(statusId, callback);
        return false;
    },
    unsetFavorite: function(statusId) {
        var self = this;
        var callback = function() {
            self._view.unsetFavorite(statusId);
        }
        this._view.settingFavorite(statusId);
        this._status.unsetFavorite(statusId, callback);
        return false;
    },
    focusKeyword: function() {
        this._view.focusKeyword();
    },
    blurKeyword: function() {
        this._view.blurKeyword();
    },
    searchUsers: function(event) {
        if (event) {
            if (event.keyCode) {
                if (event.keyCode != 13) {
                    return;
                }
            } else if (event.charCode) {
                if (event.charCode != 13) {
                    return;
                }
            } else {
                return;
            }
            $(this._idMap.inputed).val(true);
        }
        if (!eval($(this._idMap.inputed).val())) {
            $(this._idMap.keyword).val('');
        } else {
            var keyword = $(this._idMap.inputKeyword).val();
            keyword = shovel.trim(keyword);
            $(this._idMap.keyword).val(keyword);
        }
        $(this._idMap.searchForm).submit();
    }
};
shovel.FriendsController.prototype = {
    constructor: function(controllerInfo) {
        this._idMap = controllerInfo.idMap;
        this._status = new shovel.Status(controllerInfo);
        this._friendship = new shovel.Friendship(controllerInfo);
        this._view = new shovel.FriendsView(controllerInfo);
    },
    getFriendships: function() {
        var self = this;
        var callback = function(html, status) {
            self._view.getFriendships(html, status);
        };
        this._friendship.getFriendships(callback);
        return false;
    },
    getFriendshipsByPage: function(page) {
        var self = this;
        var callback = function(html, status) {
            self._view.getFriendships(html, status);
        }
        this._friendship.getFriendshipsByPage(page, callback);
        return false;
    },
    createFriendship: function(foreignKey) {
        var self = this;
        var callback = function(html, status) {
            self._view.createFriendship(foreignKey);
        };
        this._friendship.createFriendship(callback, foreignKey);
        return false;
    },
    destroyFriendship: function(foreignKey) {
        var self = this;
        var callback = function(html, status) {
            self.getFriendships();
        };
        this._friendship.destroyFriendship(callback, foreignKey);
        return false;
    },
    setNotify: function(friendshipId) {
        this._friendship.setNotify(friendshipId);
    },
    unsetNotify: function(friendshipId) {
        this._friendship.unsetNotify(friendshipId);
    },
    focusKeyword: function() {
        this._view.focusKeyword();
    },
    blurKeyword: function() {
        this._view.blurKeyword();
    },
    searchUsers: function(event) {
        if (event) {
            if (event.keyCode) {
                if (event.keyCode != 13) {
                    return;
                }
            } else if (event.charCode) {
                if (event.charCode != 13) {
                    return;
                }
            } else {
                return;
            }
            $(this._idMap.inputed).val(true);
        }
        if (!eval($(this._idMap.inputed).val())) {
            $(this._idMap.keyword).val('');
        } else {
            var keyword = $(this._idMap.inputKeyword).val();
            keyword = shovel.trim(keyword);
            $(this._idMap.keyword).val(keyword);
        }
        $(this._idMap.searchForm).submit();
    }
};
shovel.ShowStatusView.prototype = {
    constructor: function(controllerInfo) {
        this._idMap = controllerInfo.idMap;
        this._urlMap = controllerInfo.urlMap;
    },
    settingFavorite: function(statusId) {
        var html = $('#template_settingFavorite').val().process({
            statusId: statusId
        });
        $('#showStatus_favorite_' + statusId).html(html);
    },
    setFavorite: function(statusId) {
        var html = $('#template_setFavorite').val().process({
            statusId: statusId
        });
        $('#showStatus_favorite_' + statusId).html(html);
    },
    unsetFavorite: function(statusId) {
        var html = $('#template_unsetFavorite').val().process({
            statusId: statusId
        });
        $('#showStatus_favorite_' + statusId).html(html);
    },
    focusKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        if (keyword == shovel.getMessage('search.init') && !eval($('#header_inputed').val())) {
            $('#header_inputKeyword').val('');
            $('#header_inputKeyword').css('color', '#000');
        }
    },
    blurKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        keyword = shovel.trim(keyword);
        if (keyword == null || keyword.length <= 0) {
            $('#header_inputKeyword').val(shovel.getMessage('search.init'));
            $('#header_inputKeyword').css('color', '#666666');
            $('#header_inputed').val(false);
        } else {
            $('#header_inputed').val(true);
        }
    }
};
shovel.ShowStatusController.prototype = {
    constructor: function(controllerInfo) {
        this._idMap = controllerInfo.idMap;
        this._urlMap = controllerInfo.urlMap;
        this._status = new shovel.Status(controllerInfo);
        this._view = new shovel.ShowStatusView(controllerInfo);
    },
    setFavorite: function(statusId) {
        var self = this;
        var callback = function() {
            self._view.setFavorite(statusId);
        }
        this._view.settingFavorite(statusId);
        this._status.setFavorite(statusId, callback);
        return false;
    },
    unsetFavorite: function(statusId) {
        var self = this;
        var callback = function() {
            self._view.unsetFavorite(statusId);
        }
        this._view.settingFavorite(statusId);
        this._status.unsetFavorite(statusId, callback);
        return false;
    },
    destroyStatus: function(statusId) {
        var self = this;
        var callback = function(html, status) {
            location.href=self._urlMap.home;
        };
        this._status.destroyStatus(statusId, callback);
        return false;
    },
    focusKeyword: function() {
        this._view.focusKeyword();
    },
    blurKeyword: function() {
        this._view.blurKeyword();
    },
    searchUsers: function(event) {
        if (event) {
            if (event.keyCode) {
                if (event.keyCode != 13) {
                    return;
                }
            } else if (event.charCode) {
                if (event.charCode != 13) {
                    return;
                }
            } else {
                return;
            }
            $(this._idMap.inputed).val(true);
        }
        if (!eval($(this._idMap.inputed).val())) {
            $(this._idMap.keyword).val('');
        } else {
            var keyword = $(this._idMap.inputKeyword).val();
            keyword = shovel.trim(keyword);
            $(this._idMap.keyword).val(keyword);
        }
        $(this._idMap.searchForm).submit();
    }
};
shovel.RootView.prototype = {
    constructor: function(controllerInfo) {
        var self = this;
        this._controller = controllerInfo.controller;
        //if (eval($('#login_error').val())) {
            //var msg = shovel.getMessage('warning.loginFailure');
            //shovel.flashWarn('#root_flash', msg);
        //}
        if ($('#root_notify').val()) {
            var msg = shovel.getMessage($('#root_notify').val());
            shovel.flashWarn('#root_flash', msg);
        }
        //$('#root_username').focus();
        //this.focusUsername();
    },
    focusPassword: function() {
        $('#root_password').addClass('focusText');
    },
    blurPassword: function() {
        $('#root_password').removeClass('focusText');
    },
    focusUsername: function() {
        $('#root_username').addClass('focusText');
    },
    blurUsername: function() {
        $('#root_username').removeClass('focusText');
    },
    focusKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        if (keyword == shovel.getMessage('search.init') && !eval($('#header_inputed').val())) {
            $('#header_inputKeyword').val('');
            $('#header_inputKeyword').css('color', '#000');
        }
    },
    blurKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        keyword = shovel.trim(keyword);
        if (keyword == null || keyword.length <= 0) {
            $('#header_inputKeyword').val(shovel.getMessage('search.init'));
            $('#header_inputKeyword').css('color', '#666666');
            $('#header_inputed').val(false);
        } else {
            $('#header_inputed').val(true);
        }
    }
};
shovel.AccountView.prototype = {
    constructor: function(controllerInfo) {
        var self = this;
        this._controller = controllerInfo.controller;
        this._idMap = controllerInfo.idMap;
        this._urlMap = controllerInfo.urlMap;
        var tabs = new YAHOO.widget.TabView('account');
        //tabs.getTab(5).setAttributeConfig('disabled', {value: true});
        tabs.addListener('beforeActiveTabChange', function(e) {
            //"nav-"を除去
            var id = e.newValue.get('id').substring(4);
            location.href = self._urlMap[id];
            return false;
        });
        this._tabs = tabs;
        switch ($(this._idMap.viewID).val()) {
        case 'settings':
            $('#settings_displayName').focus();
            break;
        case 'password':
            $('#password_password').focus();
            break;
        default:
            break;
        }
        this._textId = '';
        this._padding = ['', '0', '00'];
    },
    updateSettings: function(html, status) {
        var msg = shovel.getMessage('notify.settings');
        shovel.flashWarn('#account_flash', msg);
    },
    updateNotices: function(html, status) {
        var msg = shovel.getMessage('notify.notices');
        shovel.flashWarn('#account_flash', msg);
    },
    onUpdatePicture: function(json, status) {
        var id = '#template_noPicture';
        if (json.serverFile.exists) {
            id = '#template_picture';
        }
        var html = $(id).val().process({
            fileName: json.serverFile.name,
            displayName: json.displayName,
            dummy: true,
            width: json.serverFile.small.width,
            height: json.serverFile.small.height,
            size: 'small'
        });
        $('#account_picture').html(html);
        html = $(id).val().process({
            fileName: json.serverFile.name,
            displayName: json.displayName,
            width: json.serverFile.large.width,
            height: json.serverFile.large.height,
            size: 'large'
        });
        $('#picture_picture').html(html);
        if (json.serverFile.exists) {
            $('#picture_fileWrapper').css('display', 'none');
            $('#picture_destroyPictureWrapper').css('display', '');
            $('#picture_submit').css('display', 'none');
        } else {
            $('#picture_fileWrapper').css('display', '');
            $('#picture_destroyPictureWrapper').css('display', 'none');
            $('#picture_submit').css('display', '');
        }
        $('#picture_file').val('');
        $('#picture_destroyPicture').removeAttr('checked');
        var msg = shovel.getMessage('notify.picture');
        shovel.flashWarn('#account_flash', msg);
    },
    onDestroyPicture: function(destroy) {
        var value = destroy ? '' : 'none';
        $('#picture_fileWrapper').css('display', value);
        $('#picture_submit').css('display', value);
    },
    mismatchPassword: function() {
        $('#password_mismatch').css('display', '');
    },
    changePassword: function() {
        $('#password_mismatch').css('display', 'none');
        var msg = shovel.getMessage('notify.password');
        shovel.flashWarn('#account_flash', msg);
    },
    conflictForeignKey: function(json, status) {
        $('#settings_notice').css('display', 'none');
        var show = '#settings_available';
        var hide1 = '#settings_already';
        var hide2 = '#settings_invalid';
        var color = 'green';
        if (json.already) {
            show = '#settings_already';
            hide1 = '#settings_available';
            color = 'red';
        } else if (json.invalid) {
            show = '#settings_invalid';
            hide2 = '#settings_available';
            color = 'red';
        }
        $(show).css('display', '');
        $(hide1).css('display', 'none');
        $(hide2).css('display', 'none');
        $('#settings_url').html(json.foreignKey);
        $('#settings_url').css('color', color);
    },
    registerDevice: function(json, status) {
        var html = shovel.unrtf($('#template_verifyDevice').val()).process({
            address: json.address,
            releaseKey: json.releaseKey
        });
        $('#device_config').html(html);
    },
    freshDevice: function(html, status) {
        var html = $('#template_registerDevice').val();
        $('#device_config').html(html);
    },
    updateDevice: function(html, status) {
    },
    testSubmit: function(possible) {
        if (possible) {
            $('#settings_submit').removeAttr('disabled');
        } else {
            $('#settings_submit').attr('disabled', 'disabled');
        }
    },
    focusKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        if (keyword == shovel.getMessage('search.init') && !eval($('#header_inputed').val())) {
            $('#header_inputKeyword').val('');
            $('#header_inputKeyword').css('color', '#000');
        }
    },
    blurKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        keyword = shovel.trim(keyword);
        if (keyword == null || keyword.length <= 0) {
            $('#header_inputKeyword').val(shovel.getMessage('search.init'));
            $('#header_inputKeyword').css('color', '#666666');
            $('#header_inputed').val(false);
        } else {
            $('#header_inputed').val(true);
        }
    },
    focusColor: function(id) {
        //ブラウザによってx座標がずれるので強制補正
        if (this._textId != id) {
            if (this._menu) {
                this._menu.destroy();
            }
            menuId = id.substring("design_".length);
            //lazyLoadがfalseだとスタイルがheight:auto
            var menu = new YAHOO.widget.Menu("color-picker-menu"/*, {lazyLoad: true}*/);
            menu.setBody("&#32;");
            menu.body.id = "color-picker-container";
            menu.render(menuId);
            $('#color-picker-container').css('height', '190px');
            var rgb = parseInt('0x' + $('#' + id).val());
            var r = (rgb & 0xff0000) >> 16;
            var g = (rgb & 0xff00) >> 8;
            var b = (rgb & 0xff);
            var picker = new YAHOO.widget.ColorPicker(menu.body.id, {
                showcontrols: false,
                images: {
                    PICKER_THUMB: "/shovel/yui/colorpicker/assets/picker_thumb.png",
                    HUE_THUMB: "/shovel/yui/colorpicker/assets/hue_thumb.png"
                }
            });
            //TODO もっとうまくやれそうな気がするけど。。
            picker.setValue([r, g, b], true);
            var self = this;
            picker.on('rgbChange', function(color) {
                var rgb = color.newValue;
                var hex = YAHOO.util.Color.rgb2hex(rgb[0], rgb[1], rgb[2]);
                self.blurColor(self._textId, hex);
            });
            this._menu = menu;
            this._textId = id;
        }
        this._menu.show();
    },
    blurColor: function(id, hex) {
        var text = $('#' + id);
        if (hex) {
            text.val(hex);
        } else {
            hex = text.val();
        }
        //css_color.vim
        //http://www.vim.org/scripts/script.php?script_id=2150
        var rgb = YAHOO.util.Color.hex2rgb(hex);
        var color = '#ffffff';
        if (rgb[0] * 30 + rgb[1] * 59 + rgb[2] * 11 > 12000) {
            color = '#000000';
        }
        text.css({'background-color': '#' + hex,
                  'color': color});
    },
    destroyBackground: function(destroy) {
        var value = destroy ? '' : 'none';
        $('#design_fileWrapper').css('display', value);
    },
    changeDesign: function(custom) {
        if (custom) {
            $('#design_backgroundColor').removeAttr('disabled');
            $('#design_file').removeAttr('disabled');
            $('#design_tileImage').removeAttr('disabled');
            $('#design_color').removeAttr('disabled');
            $('#design_nameColor').removeAttr('disabled');
            $('#design_linkColor').removeAttr('disabled');
            $('#design_sidebarBackgroundColor').removeAttr('disabled');
            $('#design_sidebarFrameColor').removeAttr('disabled');
            $('#design_destroyPicture').removeAttr('disabled');
            $('#design_file').removeAttr('disabled');
        } else {
            $('#design_backgroundColor').attr('disabled', 'disabled');
            $('#design_file').attr('disabled', 'disabled');
            $('#design_tileImage').attr('disabled', 'disabled');
            $('#design_color').attr('disabled', 'disabled');
            $('#design_nameColor').attr('disabled', 'disabled');
            $('#design_linkColor').attr('disabled', 'disabled');
            $('#design_sidebarBackgroundColor').attr('disabled', 'disabled');
            $('#design_sidebarFrameColor').attr('disabled', 'disabled');
            $('#design_destroyPicture').attr('disabled', 'disabled');
            $('#design_file').attr('disabled', 'disabled');
        }
    }
};
shovel.AccountController.prototype = {
    constructor: function(controllerInfo) {
        controllerInfo.controller = this;
        this._idMap = controllerInfo.idMap;
        this._urlMap = controllerInfo.urlMap;
        this._account = new shovel.Account(controllerInfo);
        this._view = new shovel.AccountView(controllerInfo);
    },
    updateSettings: function() {
        var self = this;
        this._account.updateSettings(function(html, status) {
            self._view.updateSettings(html, status);
        });
        return false;
    },
    updateNotices: function() {
        var self = this;
        this._account.updateNotices(function(html, status) {
            self._view.updateNotices(html, status);
        });
        return false;
    },
    updatePicture: function() {
        this._account.updatePicture();
        return false;
    },
    updateDesign: function() {
        this._account.updateDesign();
        return false;
    },
    resendPassword: function() {
        this._account.resendPassword();
        return false;
    },
    resetPassword: function() {
        var self = this;
        if (!this._account.resetPassword()) {
            this._view.mismatchPassword();
        }
        return false;
    },
    onUpdatePicture: function(json, state) {
        this._view.onUpdatePicture(json, state);
    },
    destroyPicture: function() {
        var self = this;
        this._account.destroyPicture(function(destroy) {
            self._view.onDestroyPicture(destroy);
        });
        return false;
    },
    changePassword: function() {
        var self = this;
        var callback = function(html, status) {
            self._view.changePassword(html, status);
        };
        if (!this._account.changePassword(callback)) {
            this._view.mismatchPassword();
        }
        return false;
    },
    conflictForeignKey: function() {
        var self = this;
        this._account.conflictForeignKey(function(json, status) {
            self._view.conflictForeignKey(json, status);
            self.testSubmit(json);
        });
        return false;
    },
    registerDevice: function() {
        var self = this;
        this._account.registerDevice(function(json, status) {
            self._view.registerDevice(json, status);
        });
        return false;
    },
    freshDevice: function() {
        var self = this;
        this._account.freshDevice(function(json, status) {
            self._view.freshDevice(json, status);
        });
        return false;
    },
    updateDevice: function() {
        var self = this;
        this._account.updateDevice(false, function(json, status) {
            self._view.updateDevice(json, status);
        });
        return false;
    },
    testSubmit: function(json) {
        var self = this;
        this._account.testSubmit(json, function(possible) {
            self._view.testSubmit(possible);
        });
        return false;
    },
    focusKeyword: function() {
        this._view.focusKeyword();
    },
    blurKeyword: function() {
        this._view.blurKeyword();
    },
    searchUsers: function(event) {
        if (event) {
            if (event.keyCode) {
                if (event.keyCode != 13) {
                    return;
                }
            } else if (event.charCode) {
                if (event.charCode != 13) {
                    return;
                }
            } else {
                return;
            }
            $(this._idMap.inputed).val(true);
        }
        if (!eval($(this._idMap.inputed).val())) {
            $(this._idMap.keyword).val('');
        } else {
            var keyword = $(this._idMap.inputKeyword).val();
            keyword = shovel.trim(keyword);
            $(this._idMap.keyword).val(keyword);
        }
        $(this._idMap.searchForm).submit();
    },
    focusColor: function(id) {
        this._view.focusColor(id);
    },
    blurColor: function(id) {
        this._view.blurColor(id);
    },
    destroyBackground: function() {
        var self = this;
        this._account.destroyBackground(function(destroy) {
            self._view.destroyBackground(destroy);
        });
        return false;
    },
    changeDesign: function(custom) {
        this._view.changeDesign(custom);
    },
    applyDesign: function(json) {
        $('a').css('color', json.linkColor);
        var backgroundImage = 'none';
        var backgroundRepeat = 'no-repeat';
        if (!json.defaultDesign && json.backgroundImage.exists) {
            backgroundImage = 'url(' +
                              this._urlMap.backgroundImage +
                              json.backgroundImage.name +
                              ')';
            if (json.tile) {
                backgroundRepeat = 'repeat';
            }
        }
        $('body').css('background-image', backgroundImage);
        $('body').css('background-repeat', backgroundRepeat);
        $('body').css('background-color', '#' + json.backgroundColor);
        $('body').css('color', '#' + json.color);
        $('.sidebar').css('background', '#' + json.sidebarBackgroundColor);
        var msg = shovel.getMessage('notify.design');
        shovel.flashWarn(this._idMap.flash, msg);
    },
    toggleGrowlSettings: function() {
        var display = 'none';
        if ($(this._idMap.growl).attr('checked')) {
            display = '';
        }
        $(this._idMap.growlSettings).css('display', display);
    }
};
shovel.HomeView.prototype = {
    getTabID: function(contentEl) {
        switch (contentEl) {
        case 'recent':
            tabID = 0;
            break;
        case 'replies':
            tabID = 1;
            break;
        case 'archive':
            tabID = 2;
            break;
        case 'publicTimeline':
            tabID = 3;
            break;
        defaul:
            break;
        }
        return tabID;
    },
    constructor: function(controllerInfo) {
        var self = this;
        this._controller = controllerInfo.controller;
        this._idMap = controllerInfo.idMap;
        this._urlMap = controllerInfo.urlMap;
        var tabs = new YAHOO.widget.TabView('home_timeline');
        tabs.addListener('beforeActiveTabChange', function(e) {
            //"nav-"を除去
            var id = e.newValue.get('id').substring(4);
            location.href = self._urlMap[id];
            return false;
        });
        this._tabs = tabs;
        if ($('#home_notify').val()) {
            var msg = shovel.getMessage($('#home_notify').val());
            shovel.flashWarn('#home_flash', msg);
        }
        //$('#home_status').focus();
        //this.focusInputStatus();
        if ($('#home_status').length > 0) {
            this._timer = setInterval(function() {
                self.countTyping();
            }, 500);
        }
    },
    render: function(html, status, contentEl) {
        if (html.length > 0) {
            var contents = shovel.splitResponseByBoundary();
            $('#home_sidebar').html(contents[0]);
            if (!contentEl) {
                contentEl = $(this._idMap.viewID).val();
            }
            $('#' + contentEl).html(contents[1]);
        }
    },
    settingFavorite: function(statusId) {
        var html = $('#template_settingFavorite').val().process({
            statusId: statusId
        });
        $('#home_favorite_' + statusId).html(html);
    },
    setFavorite: function(statusId) {
        var html = $('#template_setFavorite').val().process({
            statusId: statusId
        });
        $('#home_favorite_' + statusId).html(html);
        $('#home_favorite_' + statusId).addClass('favorite');
        
        var favorites = $('#home_favorites').html();
        favorites = parseInt(favorites) + 1;
        $('#home_favorites').html(favorites.toString());
    },
    unsetFavorite: function(statusId) {
        var html = $('#template_unsetFavorite').val().process({
            statusId: statusId
        });
        $('#home_favorite_' + statusId).html(html);
        $('#home_favorite_' + statusId).removeClass('favorite');
        
        var favorites = $('#home_favorites').html();
        favorites = parseInt(favorites) - 1;
        $('#home_favorites').html(favorites.toString());
    },
    countTyping: function() {
        var count = $('#home_status').val().length;
        count = 140 - parseInt(count);
        var color = '#cccccc';
        if (count < 0) {
            color = '#ff0000';
        }
        $('#home_typeCount').css('color', color);
        $('#home_typeCount').html(count.toString());
    },
    clearStatus: function() {
        $(this._idMap.status).val('');
    },
    focusKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        if (keyword == shovel.getMessage('search.init') && !eval($('#header_inputed').val())) {
            $('#header_inputKeyword').val('');
            $('#header_inputKeyword').css('color', '#000');
        }
    },
    blurKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        keyword = shovel.trim(keyword);
        if (keyword == null || keyword.length <= 0) {
            $('#header_inputKeyword').val(shovel.getMessage('search.init'));
            $('#header_inputKeyword').css('color', '#666666');
            $('#header_inputed').val(false);
        } else {
            $('#header_inputed').val(true);
        }
    },
    focusInputStatus: function() {
        $('#home_status').addClass('focusText');
    },
    blurInputStatus: function() {
        $('#home_status').removeClass('focusText');
    },
    focusStatus: function(statusId) {
        //$('#home_status_action_' + statusId).css('display', '');
        $('#home_favorite_' + statusId).css('display', '');
        $('#home_destroyStatus_' + statusId).css('display', '');
        $('#home_replyStatus_' + statusId).css('display', '');
    },
    blurStatus: function(statusId) {
        //$('#home_status_action_' + statusId).css('display', 'none');
        var fav = $('#home_favorite_' + statusId);
        if (!fav.hasClass('favorite')) {
          fav.css('display', 'none');
        }
        $('#home_destroyStatus_' + statusId).css('display', 'none');
        $('#home_replyStatus_' + statusId).css('display', 'none');
    }
};
shovel.DirectMessagesView.prototype = {
    getTabID: function(contentEl) {
        switch (contentEl) {
        case 'inbox':
            tabID = 0;
            break;
        case 'sent':
            tabID = 1;
            break;
        defaul:
            break;
        }
        return tabID;
    },
    constructor: function(controllerInfo) {
        var self = this;
        this._controller = controllerInfo.controller;
        this._idMap = controllerInfo.idMap;
        this._urlMap = controllerInfo.urlMap;
        var tabs = new YAHOO.widget.TabView('directMessages_timeline');
        tabs.addListener('beforeActiveTabChange', function(e) {
            //"nav-"を除去
            var id = e.newValue.get('id').substring(4);
            location.href = self._urlMap[id];
            return false;
        });
        this._tabs = tabs;
        if ($('#directMessages_text').length > 0) {
            this._timer = setInterval(function() {
                self.countTyping();
            }, 500);
        }
        //$('#directMessages_recipient').focus();
    },
    render: function(html, status, contentEl) {
        if (html.length > 0) {
            var contents = shovel.splitResponseByBoundary();
            $('#directMessages_sidebar').html(contents[0]);
            var content = shovel.trim(contents[1]);
            if (content.length > 0) {
                var id = $('#directMessages_viewID').val();
                $('#' + id).html(content);
            }
        }
    },
    countTyping: function() {
        var count = $('#directMessages_text').val().length;
        count = 140 - parseInt(count);
        var color = '#000000';
        if (count < 0) {
            color = '#ff0000';
        }
        $('#directMessages_typeCount').css('color', color);
        $('#directMessages_typeCount').html(count.toString());
    },
    clearDirectMessage: function() {
        $(this._idMap.text).val('');
    },
    focusInputDirectMessage: function() {
        $('#directMessages_text').addClass('focusText');
    },
    blurInputDirectMessage: function() {
        $('#directMessages_text').removeClass('focusText');
    },
    focusDirectMessage: function(directMessageId) {
        $('#directMessages_directMessage_action_' + directMessageId).css('display', '');
    },
    blurDirectMessage: function(directMessageId) {
        $('#directMessages_directMessage_action_' + directMessageId).css('display', 'none');
    },
    focusKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        if (keyword == shovel.getMessage('search.init') && !eval($('#header_inputed').val())) {
            $('#header_inputKeyword').val('');
            $('#header_inputKeyword').css('color', '#000');
        }
    },
    blurKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        keyword = shovel.trim(keyword);
        if (keyword == null || keyword.length <= 0) {
            $('#header_inputKeyword').val(shovel.getMessage('search.init'));
            $('#header_inputKeyword').css('color', '#666666');
            $('#header_inputed').val(false);
        } else {
            $('#header_inputed').val(true);
        }
    }
};
shovel.PeopleView.prototype = {
    constructor: function(controllerInfo) {
        var self = this;
        this._idMap = controllerInfo.idMap;
        this._urlMap = controllerInfo.urlMap;
        this._myself = controllerInfo.login == controllerInfo.foreignKey;
        /*
        var tabs = new YAHOO.widget.TabView('people_timeline');
        tabs.addListener('beforeActiveTabChange', function(e) {
            //"nav-"を除去
            var id = e.newValue.get('id').substring(4);
            location.href = self._urlMap[id];
            return false;
        });
        this._tabs = tabs;
        */
    },
    render: function(html, status, contentEl) {
        if (html.length > 0) {
            var contents = shovel.splitResponseByBoundary();
            $('#people_sidebar').html(contents[0]);
            if (!contentEl) {
                contentEl = $(this._idMap.viewID).val();
            }
            $('#' + contentEl).html(contents[1]);
        }
    },
    createFriendship: function() {
        $('#people_createFriendship').css('display', 'none');
        $('#people_destroyFriendship').css('display', '');
        if (!eval($('#people_protect').val())) {
            var el = $('#people_followers');
            if (el.length > 0) {
               var followers = el.html();
               followers = parseInt(followers) + 1;
               el.html(followers.toString());
            }
        }
    },
    destroyFriendship: function() {
        if (eval($('#people_protect').val())) {
            var viewID = $(this._idMap.viewID).val();
            var url = this._urlMap[viewID];
            location.href = url + '?';
        } else {
            $('#people_createFriendship').css('display', '');
            $('#people_destroyFriendship').css('display', 'none');
            var el = $('#people_followers');
            if (el.length > 0) {
                var followers = el.html();
                followers = parseInt(followers) - 1;
                el.html(followers.toString());
            }
        }
    },
    acceptFriendRequest: function() {
        var viewID = $(this._idMap.viewID).val();
        var url = this._urlMap[viewID];
        location.href = url + '?';
    },
    denyFriendRequest: function() {
        var viewID = $(this._idMap.viewID).val();
        var url = this._urlMap[viewID];
        location.href = url + '?';
    },
    settingFavorite: function(statusId) {
        var html = $('#template_settingFavorite').val().process({
            statusId: statusId
        });
        $('#people_favorite_' + statusId).html(html);
    },
    setFavorite: function(statusId) {
        var html = $('#template_setFavorite').val().process({
            statusId: statusId
        });
        $('#people_favorite_' + statusId).html(html);
        $('#people_favorite_' + statusId).addClass('favorite');
        
        //自分のときだけカウンタ回す
        if (this._myself) {
            var favorites = $('#people_favorites').html();
            favorites = parseInt(favorites) + 1;
            $('#people_favorites').html(favorites.toString());
        }
    },
    unsetFavorite: function(statusId) {
        var html = $('#template_unsetFavorite').val().process({
            statusId: statusId
        });
        $('#people_favorite_' + statusId).html(html);
        $('#people_favorite_' + statusId).removeClass('favorite');
        
        //自分のときだけカウンタ回す
        if (this._myself) {
            var favorites = $('#people_favorites').html();
            favorites = parseInt(favorites) - 1;
            $('#people_favorites').html(favorites.toString());
        }
    },
    focusKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        if (keyword == shovel.getMessage('search.init') && !eval($('#header_inputed').val())) {
            $('#header_inputKeyword').val('');
            $('#header_inputKeyword').css('color', '#000');
        }
    },
    blurKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        keyword = shovel.trim(keyword);
        if (keyword == null || keyword.length <= 0) {
            $('#header_inputKeyword').val(shovel.getMessage('search.init'));
            $('#header_inputKeyword').css('color', '#666666');
            $('#header_inputed').val(false);
        } else {
            $('#header_inputed').val(true);
        }
    }
};
shovel.FavoritesView.prototype = {
    constructor: function(controllerInfo) {
        var self = this;
        this._controller = controllerInfo.controller;
        this._idMap = controllerInfo.idMap;
        this._urlMap = controllerInfo.urlMap;
    },
    render: function(html, status) {
        if (html.length > 0) {
            var contents = shovel.splitResponseByBoundary();
            $(this._idMap.sidebar).html(contents[0]);
            $('#favorites_timeline').html(contents[1]);
        }
    },
    createFriendship: function() {
        $('#favorites_createFriendship').css('display', 'none');
        $('#favorites_destroyFriendship').css('display', '');
        if (!eval($('#favorites_protect').val())) {
            var el = $('#favorites_followers');
            if (el.length > 0) {
               var followers = el.html();
               followers = parseInt(followers) + 1;
               el.html(followers.toString());
            }
        }
    },
    destroyFriendship: function() {
        if (eval($('#favorites_protect').val())) {
            var viewID = $(this._idMap.viewID).val();
            var url = this._urlMap[viewID];
            location.href = url + '?';
        } else {
            $('#favorites_createFriendship').css('display', '');
            $('#favorites_destroyFriendship').css('display', 'none');
            var el = $('#favorites_followers');
            if (el.length > 0) {
                var followers = el.html();
                followers = parseInt(followers) - 1;
                el.html(followers.toString());
            }
        }
    },
    acceptFriendRequest: function() {
        var viewID = $(this._idMap.viewID).val();
        var url = this._urlMap[viewID];
        location.href = url + '?';
    },
    denyFriendRequest: function() {
        var viewID = $(this._idMap.viewID).val();
        var url = this._urlMap[viewID];
        location.href = url + '?';
    },
    settingFavorite: function(statusId) {
        var html = $('#template_settingFavorite').val().process({
            statusId: statusId
        });
        $(this._idMap.favorite + '_' + statusId).html(html);
    },
    setFavorite: function(statusId) {
        var html = $('#template_setFavorite').val().process({
            statusId: statusId
        });
        $(this._idMap.favorite + '_' + statusId).html(html);
        $(this._idMap.favorite + '_' + statusId).addClass('favorite');
        
        var favorites = $(this._idMap.favorites).html();
        favorites = parseInt(favorites) + 1;
        $(this._idMap.favorites).html(favorites.toString());
    },
    unsetFavorite: function(statusId) {
        var html = $('#template_unsetFavorite').val().process({
            statusId: statusId
        });
        $(this._idMap.favorite + '_' + statusId).html(html);
        $(this._idMap.favorite + '_' + statusId).removeClass('favorite');
        
        var favorites = $(this._idMap.favorites).html();
        favorites = parseInt(favorites) - 1;
        $(this._idMap.favorites).html(favorites.toString());
    },
    focusKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        if (keyword == shovel.getMessage('search.init') && !eval($('#header_inputed').val())) {
            $('#header_inputKeyword').val('');
            $('#header_inputKeyword').css('color', '#000');
        }
    },
    blurKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        keyword = shovel.trim(keyword);
        if (keyword == null || keyword.length <= 0) {
            $('#header_inputKeyword').val(shovel.getMessage('search.init'));
            $('#header_inputKeyword').css('color', '#666666');
            $('#header_inputed').val(false);
        } else {
            $('#header_inputed').val(true);
        }
    }
};
shovel.FriendsView.prototype = {
    constructor: function(controllerInfo) {
        var self = this;
        this._idMap = controllerInfo.idMap;
        this._urlMap = controllerInfo.urlMap;
    },
    getFriendships: function(html, status) {
        if (html.length > 0) {
            $('#friends_friendships').html(html);
        }
    },
    createFriendship: function(foreignKey) {
        $('#friends_createFriendship_' + foreignKey).css('display', 'none');
        $('#friends_friends_' + foreignKey).css('display', '');
        var el = $('#friends_followers');
        if (el.length > 0) {
           var followers = el.html();
           followers = parseInt(followers) + 1;
           el.html(followers.toString());
        }
    },
    destroyFriendship: function(foreignKey) {
        $('#friends_destroyFriendship_' + foreignKey).css('display', 'none');
        var el = $('#friends_followers');
        if (el.length > 0) {
            var followers = el.html();
            followers = parseInt(followers) - 1;
            el.html(followers.toString());
        }
    },
    focusKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        if (keyword == shovel.getMessage('search.init') && !eval($('#header_inputed').val())) {
            $('#header_inputKeyword').val('');
            $('#header_inputKeyword').css('color', '#000');
        }
    },
    blurKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        keyword = shovel.trim(keyword);
        if (keyword == null || keyword.length <= 0) {
            $('#header_inputKeyword').val(shovel.getMessage('search.init'));
            $('#header_inputKeyword').css('color', '#666666');
            $('#header_inputed').val(false);
        } else {
            $('#header_inputed').val(true);
        }
    }
};
shovel.SystemView.prototype = {
    constructor: function(controllerInfo) {
        this._idMap = controllerInfo.idMap;
        this._urlMap = controllerInfo.urlMap;
        var tabs = new YAHOO.widget.TabView('system_config');
        tabs.addListener('beforeActiveTabChange', function(e) {
            //"nav-"を除去
            var id = e.newValue.get('id').substring(4);
            location.href = self._urlMap[id];
            return false;
        });
        this._tabs = tabs;
    },
    changeConfig: function(html, status) {
        if (html.length > 0) {
            $('#accounts').html(html);
        }
    },
    onConflictForeignKey: function(json, status) {
        $('#users_notice').css('display', 'none');
        var show = '#users_available';
        var hide1 = '#users_already';
        var hide2 = '#users_invalid';
        var color = 'green';
        if (json.already) {
            show = '#users_already';
            hide1 = '#users_available';
            color = 'red';
        } else if (json.invalid) {
            show = '#users_invalid';
            hide2 = '#users_available';
            color = 'red';
        }
        $(show).css('display', '');
        $(hide1).css('display', 'none');
        $(hide2).css('display', 'none');
        $('#users_url').html(json.foreignKey);
        $('#users_url').css('color', color);
    },
    onTestSubmit: function(possible) {
        if (possible) {
            $('#users_submit').removeAttr('disabled');
        } else {
            $('#users_submit').attr('disabled', 'disabled');
        }
    },
    onDestroyPicture: function(destroy) {
        var display = 'none';
        if (destroy) {
            display = '';
        }
        $('#users_fileWrapper').css('display', display);
    },
    render: function(html, status) {
        if (html.length > 0) {
            $('#accounts').html(html);
        }
    },
    sortUsersByAsc: function() {
        $('#accounts_asc').css('display', '');
        $('#accounts_desc').css('display', 'none');
    },
    sortUsersByDesc: function() {
        $('#accounts_asc').css('display', 'none');
        $('#accounts_desc').css('display', '');
    },
    focusKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        if (keyword == shovel.getMessage('search.init') && !eval($('#header_inputed').val())) {
            $('#header_inputKeyword').val('');
            $('#header_inputKeyword').css('color', '#000');
        }
    },
    blurKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        keyword = shovel.trim(keyword);
        if (keyword == null || keyword.length <= 0) {
            $('#header_inputKeyword').val(shovel.getMessage('search.init'));
            $('#header_inputKeyword').css('color', '#666666');
            $('#header_inputed').val(false);
        } else {
            $('#header_inputed').val(true);
        }
    }
}
shovel.SystemController.prototype = {
    constructor: function(controllerInfo) {
        this._idMap = controllerInfo.idMap;
        this._account = new shovel.Account(controllerInfo);
        this._view = new shovel.SystemView(controllerInfo);
    },
    changeConfig: function(type) {
        var self = this;
        this._account.changeConfig(type, function(html, status) {
            self._view.changeConfig(html, status)
        });
        return false;
    },
    onChangeConfig: function(html, status) {
        this._view.changeConfig(html, status);
    },
    switchCreateAccount: function() {
        var type = 'accounts/create';
        this.changeConfig(type);
        return false;
    },
    switchImportAccounts: function() {
        var type = 'accounts/import';
        this.changeConfig(type);
        return false;
    },
    switchUpdateAccount: function(userId) {
        var type = 'accounts/update/' + userId;
        this.changeConfig(type);
        return false;
    },
    switchAccounts: function(userId) {
        var type = 'accounts';
        this.changeConfig(type);
        return false;
    },
    destroyAccounts: function() {
        var self = this;
        this._account.destroyAccounts(function(html, status) {
            self._view.changeConfig(html, status);
        });
        return false;
    },
    importAccounts: function() {
        this._account.importAccounts();
        return false;
    },
    getUsersByPage: function(page, contentEl) {
        var self = this;
        var callback = function(html, status) {
            self._view.render(html, status, contentEl);
        };
        this._account.getUsersByPage(page, callback);
        return false;
    },
    getSortedUsers: function(desc, contentEl) {
        var self = this;
        var callback = function(html, status) {
            self._view.render(html, status, contentEl);
            if (desc) {
                self._view.sortUsersByDesc();
            } else {
                self._view.sortUsersByAsc();
            }
        };
        this._account.getUsersBySort(desc, callback);
        return false;
    },
    toggleAccount: function() {
        this._account.toggleAccount();
        return false;
    },
    toggleAllAccount: function() {
        this._account.toggleAllAccount();
        return false;
    },
    conflictForeignKey: function() {
        var self = this;
        this._account.conflictForeignKey(function(json, status) {
            self._view.onConflictForeignKey(json, status);
            self.testSubmit(json);
        });
        return false;
    },
    testSubmit: function(json) {
        var self = this;
        this._account.testSubmit(json, function(possible) {
            self._view.onTestSubmit(possible);
        });
    },
    destroyPicture: function() {
        var self = this;
        this._account.destroyPicture(function(destroy) {
            self._view.onDestroyPicture(destroy);
        });
        return false;
    },
    updateAccount: function() {
        //とりあえず。
        var checked = $('#users_administrator').attr('checked');
        $('#system_administrator').val(checked);
    },
    focusKeyword: function() {
        this._view.focusKeyword();
    },
    blurKeyword: function() {
        this._view.blurKeyword();
    },
    searchUsers: function(event) {
        if (event) {
            if (event.keyCode) {
                if (event.keyCode != 13) {
                    return;
                }
            } else if (event.charCode) {
                if (event.charCode != 13) {
                    return;
                }
            } else {
                return;
            }
            $(this._idMap.inputed).val(true);
        }
        if (!eval($(this._idMap.inputed).val())) {
            $(this._idMap.keyword).val('');
        } else {
            var keyword = $(this._idMap.inputKeyword).val();
            keyword = shovel.trim(keyword);
            $(this._idMap.keyword).val(keyword);
        }
        $(this._idMap.searchForm).submit();
    }
}
shovel.SearchUsersController.prototype = {
    constructor: function(controllerInfo) {
        this._idMap = controllerInfo.idMap;
        this._friendship = new shovel.Friendship(controllerInfo);
        this._account = new shovel.Account(controllerInfo);
        this._view = new shovel.SearchUsersView(controllerInfo);
    },
    createFriendship: function(foreignKey) {
        var self = this;
        var callback = function(html, status) {
            self._view.createFriendship(foreignKey);
        }
        this._friendship.createFriendship(callback, foreignKey);
        return false;
    },
    destroyFriendship: function(foreignKey) {
        var self = this;
        var callback = function(html, status) {
            self._view.destroyFriendship(foreignKey);
        }
        this._friendship.destroyFriendship(callback, foreignKey);
        return false;
    },
    focusKeyword: function() {
        this._view.focusKeyword();
    },
    blurKeyword: function() {
        this._view.blurKeyword();
    },
    searchUsersByPage: function(page) {
        var self = this;
        var callback = function(html, status) {
            self._view.render(html, status);
        };
        this._account.searchUsersByPage(page, callback);
        return false;
    },
    searchUsersByAjax: function(event) {
        if (event) {
            if (event.keyCode) {
                if (event.keyCode != 13) {
                    return false;
                }
            } else if (event.charCode) {
                if (event.charCode != 13) {
                    return false;
                }
            } else {
                return false;
            }
            $(this._idMap.inputed).val(true);
        }
        if (!eval($(this._idMap.inputed).val())) {
            $(this._idMap.keyword).val('');
        } else {
            var keyword = $(this._idMap.inputKeyword).val();
            keyword = shovel.trim(keyword);
            $(this._idMap.keyword).val(keyword);
        }
        var self = this;
        var callback = function(html, status) {
            self._view.render(html, status);
        }
        this._account.searchUsers(callback);
        return false;
    },
    searchUsers: function(event) {
        if (event) {
            if (event.keyCode) {
                if (event.keyCode != 13) {
                    return;
                }
            } else if (event.charCode) {
                if (event.charCode != 13) {
                    return;
                }
            } else {
                return;
            }
            $(this._idMap.inputed).val(true);
        }
        if (!eval($(this._idMap.inputed).val())) {
            $(this._idMap.keyword).val('');
        } else {
            var keyword = $(this._idMap.inputKeyword).val();
            keyword = shovel.trim(keyword);
            $(this._idMap.keyword).val(keyword);
        }
        $(this._idMap.searchForm).submit();
        return false;
    }
}
shovel.SearchUsersView.prototype = {
    constructor: function(controllerInfo) {
        this._idMap = controllerInfo.idMap;
        this._urlMap = controllerInfo.urlMap;
    },
    render: function(html, status) {
        if (html.length > 0) {
            $('#searchUsers_users').html(html);
        }
    },
    createFriendship: function(foreignKey) {
        $('#searchUsers_createFriendship_' + foreignKey).css('display', 'none');
        $('#searchUsers_destroyFriendship_' + foreignKey).css('display', '');
    },
    destroyFriendship: function(foreignKey) {
        $('#searchUsers_createFriendship_' + foreignKey).css('display', '');
        $('#searchUsers_destroyFriendship_' + foreignKey).css('display', 'none');
    },
    focusKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        if (keyword == shovel.getMessage('search.init') && !eval($('#header_inputed').val())) {
            $('#header_inputKeyword').val('');
            $('#header_inputKeyword').css('color', '#000');
        }
    },
    blurKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        keyword = shovel.trim(keyword);
        if (keyword == null || keyword.length <= 0) {
            $('#header_inputKeyword').val(shovel.getMessage('search.init'));
            $('#header_inputKeyword').css('color', '#666666');
            $('#header_inputed').val(false);
        } else {
            $('#header_inputed').val(true);
        }
    }
}
shovel.FriendRequestsController.prototype = {
    constructor: function(controllerInfo) {
        this._idMap = controllerInfo.idMap;
        this._friendship = new shovel.Friendship(controllerInfo);
        this._view = new shovel.FriendRequestsView(controllerInfo);
    },
    getFriendRequests: function() {
        var self = this;
        var callback = function(html, status) {
            self._view.getFriendRequests(html, status);
        };
        this._friendship.getFriendRequests(callback);
        return false;
    },
    getFriendRequestsByPage: function(page) {
        var self = this;
        var callback = function(html, status) {
            self._view.getFriendRequests(html, status);
        }
        this._friendship.getFriendshipsByPage(page, callback);
        return false;
    },
    acceptFriendRequest: function(foreignKey) {
        var self = this;
        var callback = function(html, status) {
            self.getFriendRequests();
        };
        this._friendship.acceptFriendRequest(foreignKey, callback);
        return false;
    },
    denyFriendRequest: function(foreignKey) {
        var self = this;
        var callback = function(html, status) {
            self.getFriendRequests();
        };
        this._friendship.denyFriendRequest(foreignKey, callback);
        return false;
    },
    focusKeyword: function() {
        this._view.focusKeyword();
    },
    blurKeyword: function() {
        this._view.blurKeyword();
    },
    searchUsers: function(event) {
        if (event) {
            if (event.keyCode) {
                if (event.keyCode != 13) {
                    return;
                }
            } else if (event.charCode) {
                if (event.charCode != 13) {
                    return;
                }
            } else {
                return;
            }
            $(this._idMap.inputed).val(true);
        }
        if (!eval($(this._idMap.inputed).val())) {
            $(this._idMap.keyword).val('');
        } else {
            var keyword = $(this._idMap.inputKeyword).val();
            keyword = shovel.trim(keyword);
            $(this._idMap.keyword).val(keyword);
        }
        $(this._idMap.searchForm).submit();
    }
};
shovel.FriendRequestsView.prototype = {
    constructor: function(controllerInfo) {
        var self = this;
        this._idMap = controllerInfo.idMap;
        this._urlMap = controllerInfo.urlMap;
    },
    getFriendRequests: function(html, status) {
        if (html.length > 0) {
            $('#friendRequests_requests').html(html);
        }
    },
    focusKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        if (keyword == shovel.getMessage('search.init') && !eval($('#header_inputed').val())) {
            $('#header_inputKeyword').val('');
            $('#header_inputKeyword').css('color', '#000');
        }
    },
    blurKeyword: function() {
        var keyword = $('#header_inputKeyword').val();
        keyword = shovel.trim(keyword);
        if (keyword == null || keyword.length <= 0) {
            $('#header_inputKeyword').val(shovel.getMessage('search.init'));
            $('#header_inputKeyword').css('color', '#666666');
            $('#header_inputed').val(false);
        } else {
            $('#header_inputed').val(true);
        }
    }
};

$().ajaxStart(function() {
    $('#loader').css('display', '');
});
$().ajaxStop(function() {
    $('#loader').css('display', 'none');
});
$().ajaxComplete(function(event, request, settings) {
    if (request == null) {
        return;
    }
    //TODO ログインが必要ならログイン画面にリダイレクト
    if (request.getResponseHeader('X-Login') == 1) {
        var href = location.href;
        //TODO 簡易フラグメント除去（URLを再構築すべきかも。。）
        var index = href.indexOf('#');
        if (index != -1) {
            href = href.substring(0, index);
        }
        location.href = href;
        return true;
    }
    if (request.status > 300 && request.status < 304) {
        location.href = reqeust.getResponseHeader('Location');
        return true;
    }
    if (request.getResponseHeader('X-Error')) {
        var args = eval('(' + request.responseText + ')');
        return shovel.showApplicationError(args);
    }
});
$().ajaxError(shovel.showAjaxError);

shovel.init();
window.shovel = shovel;
})();
