Ext.regApplication({
    name: "bandcast",
    config: _config,
    tabletStartupScreen: "resources/img/tablet_startup.png",
    phoneStartupScreen: "resources/img/phone_startup.png",
    icon: "resources/img/icon_57.png",
    statusBarStyle: "black",
    flashes: {},
    launch: function() {
        try {
            this.hacks();
            Ext.data.auth = Ext.ModelMgr.create({}, "Auth");
            Ext.data.cookies = new Ext.util.LocalStorageCookie({
                proxyId: "com.bandcast.cookies"
            });
            this.setup();
        } catch (a) {
            Ext.Msg.alert("Fatal error", "Whoops! Something went horribly wrong. Please try again later.<br />(" + a + ")", Ext.emptyFn);
            return false;
        }
    },
    setup: function() {
        this.defaultUrl = bandcast.config.event.type + "/index";
        Ext.Dispatcher.addListener("before-dispatch", function(b) {
            if (navigator.onLine) {
                this.online();
            } else {
                this.offline();
            }
            if (!Ext.data.auth.get("sid")) {
                var a = Ext.getCmp("viewport");
                if (a) {
                    a.destroy();
                }
                if (b.controller.id != "auth") {
                    this.authorize(b.historyUrl);
                    return false;
                }
            }
            return true;
        }, this);
    },
    authorize: function(b) {
        var a = new Ext.LoadMask(Ext.getBody(), {
            msg: "Authorizing"
        });
        a.show();
        Ext.data.auth.restore(Ext.createDelegate(function(d, e) {
            a.hide();
            var c = Ext.createDelegate(function() {
                a.msg = "Loading";
                a.show();
                bandcast.stores.Event.load({
                    callback: function(g, f, h) {
                        a.hide();
                        delete a;
                        if (h) {
                            Ext.dispatch({
                                controller: bandcast.config.event.type,
                                action: "run",
                                url: b
                            });
                        } else {
                            this.offline();
                        }
                    },
                    scope: this
                });
            }, this);
            if (d) {
                c();
            } else {
                Ext.dispatch({
                    controller: "auth",
                    action: "index",
                    callback: c
                });
            }
        }, this));
    },
    offline: function() {
        var a = Ext.getCmp("viewport");
        if (a) {
            a.addDocked({
                id: "offline",
                xtype: "toolbar",
                title: "offline mode - unable to establish a connection"
            });
        } else {
            Ext.Msg.alert("Offline error", "Unable to establish a connection. Please try again later.", Ext.emptyFn);
        }
    },
    online: function() {
        var a = Ext.getCmp("offline");
        if (a) {
            Ext.getCmp("viewport").removeDocked(a, false);
        }
    },
    timezoned: function(a) {
        var c = new Date(a.getTime());
        if (typeof this.config.event.date.timezone != "undefined") {
            var b = a.getTimezoneOffset() + this.config.event.date.timezone * 60;
            c.setTime(a.getTime() + b * 6e4);
        }
        return c;
    },
    timeago: function(b, a) {
        if (typeof b == "string") {
            b = new Date(Date.parseDate(b, "c"));
        }
        var d = [ "second", "minute", "hour", "day" ], f = [ 60, 60, 24, 7 ], e = Math.round(Ext.util.Date.getElapsed(b) / 1e3);
        for (var c = 0; e >= f[c] && c < f.length - 1; c++) {
            e /= f[c];
        }
        return (e = Math.round(e)) + (a ? d[c].substr(0, 1) : " " + d[c] + (e > 1 ? "s" : ""));
    },
    hacks: function() {
        resetMsgBox = function() {
            Ext.Msg = new Ext.MessageBox;
            Ext.Msg.on({
                hide: function(a) {
                    a.destroy();
                },
                destroy: function(a) {
                    resetMsgBox();
                }
            });
        };
        resetMsgBox();
    }
});

Ext.Router.draw(function(a) {
    a.connect("user/-/:username", {
        controller: "user",
        action: "detail"
    });
    a.connect("event/-/:event", {
        controller: "event",
        action: "detail"
    });
    a.connect("artist/-/:artist", {
        controller: "artist",
        action: "detail"
    });
    a.connect("venue/-/:venue", {
        controller: "venue",
        action: "detail"
    });
    a.connect("qr/friend/:username/:qrcode", {
        controller: "qrcode",
        action: "friend"
    });
    a.connect(":controller/:action");
});

Ext.util.LocalStorageCookie = Ext.extend(Object, {
    proxyId: "com.domain.cookies",
    constructor: function(a) {
        this.config = Ext.apply(this, a);
        Ext.regModel("LocalStorageCookie", {
            fields: [ "id", "key", "value" ],
            proxy: {
                type: "localstorage",
                id: this.proxyId
            }
        });
        this.store = new Ext.data.Store({
            model: "LocalStorageCookie"
        });
        this.store.load();
    },
    get: function(c) {
        var b = this.store.find("key", c);
        if (b == -1) {
            return null;
        } else {
            var a = this.store.getAt(b);
            return a.get("value");
        }
    },
    set: function(c, d) {
        var b = this.store.find("key", c);
        if (b == -1) {
            var a = Ext.ModelMgr.create({
                key: c,
                value: d
            }, "LocalStorageCookie");
        } else {
            var a = this.store.getAt(b);
            a.set("value", d);
        }
        return a.save();
    }
});

Ext.data.BandcastProxy = Ext.extend(Ext.data.RestProxy, {
    apiHost: bandcast.config.defaults.urls.api,
    appId: bandcast.config.event.id,
    pageParam: "page",
    limitParam: "num",
    defaultPage: 1,
    perPage: 50,
    appendId: false,
    constructor: function(a) {
        a = a || {};
        Ext.applyIf(a, {
            extraParams: {
                page: this.defaultPage,
                num: this.perPage
            }
        });
        Ext.data.BandcastProxy.superclass.constructor.call(this, a);
    },
    setUrl: function(a) {
        this.url = a;
    },
    buildUrl: function(d) {
        var b = Ext.data.BandcastProxy.superclass.buildUrl.call(this, d), c, a;
        b = b.indexOf("?") == -1 ? b + ".json" : b.replace("?", ".json?");
        if (Ext.data.cookies && (c = Ext.data.cookies.get("auth"))) {
            b = Ext.urlAppend(b, Ext.util.Format.format("{0}={1}", "auth", c));
        }
        if (Ext.data.auth && (a = Ext.data.auth.get("sid"))) {
            b = Ext.urlAppend(b, Ext.util.Format.format("{0}={1}", "sid", a));
        }
        return this.apiHost + b.replace("/proxy", "/proxy/app=" + this.appId);
    }
});

Ext.data.ProxyMgr.registerType("bandcast", Ext.data.BandcastProxy);

Ext.data.BandcastStore = Ext.extend(Ext.data.Store, {
    proxyType: "online",
    loaded: false,
    constructor: function(a) {
        Ext.data.BandcastStore.superclass.constructor.call(this, a);
        this.onlineProxy = this.getProxy();
        this.localProxy = Ext.data.ProxyMgr.create({
            model: this.onlineProxy.getModel(),
            type: "localstorage",
            id: this.storeId + "Local"
        });
        this.addEvents("afterload");
    },
    swapProxy: function(a) {
        switch (a) {
          case "online":
            if (this.setProxy(this.onlineProxy) instanceof Ext.data.ServerProxy) {
                return this.proxyType = "online";
            }
            break;
          case "local":
            if (this.setProxy(this.localProxy) instanceof Ext.data.LocalStorageProxy) {
                return this.proxyType = "local";
            }
            break;
        }
    },
    listeners: {
        beforesync: function(a) {
            if (this.proxyType == "online") {
                if (this.swapProxy("local")) {
                    this.proxy.batch(a, this.getBatchListeners());
                    this.sync();
                    this.swapProxy("online");
                }
            }
        },
        beforeload: function(a) {
            if (!navigator.onLine) {
                this.swapProxy("local");
            }
        },
        load: function(b, a, c) {
            if (c) {
                if (this.proxyType == "online") {
                    if (this.swapProxy("local")) {
                        this.each(function(d) {
                            d.setDirty();
                        });
                        this.sync();
                        this.swapProxy("online");
                    }
                }
                this.loaded = true;
            }
            if (this.hasListener("afterload")) {
                this.fireEvent("afterload", b, a, c);
            }
        }
    }
});

Ext.util.BandcastFlash = new (Ext.extend(Object, {
    messages: [],
    add: function(b, a) {
        a = Ext.applyIf(a || {}, {
            id: (new Date).getTime(),
            timer: 0
        });
        this.messages.unshift({
            id: a.id,
            message: b,
            added: new Date
        });
        if (a.timer > 0) {
            (new Ext.util.DelayedTask(function() {
                this.remove(a.id);
            }, this)).delay(a.timer);
        }
        this.display();
        return a.id;
    },
    remove: function(b) {
        for (var a in this.messages) {
            if (this.messages[a].id == b) {
                this.messages.splice(a, 1);
                break;
            }
        }
        this.display();
    },
    display: function() {
        if (!this.flashbar) {
            Ext.getCmp("viewport").addDocked({
                id: "flashbar",
                xtype: "toolbar"
            });
            this.flashbar = Ext.getCmp("flashbar");
        }
        if (this.messages.length) {
            this.flashbar.setTitle(this.messages[0].message);
        } else {
            Ext.getCmp("viewport").removeDocked(this.flashbar, false);
            this.flashbar = null;
        }
    },
    error: function(a, b) {
        if (b && typeof b == "object") {
            a += " " + b.join(". ") + ".";
        }
        Ext.Msg.alert("Error", a, Ext.emptyFn);
    }
}));

bandcast.models.Auth = Ext.regModel("Auth", {
    fields: [ {
        name: "sid",
        type: "string"
    }, {
        name: "auth",
        type: "string"
    }, {
        name: "user",
        type: "auto"
    } ],
    proxy: {
        type: "bandcast",
        reader: {
            type: "json",
            root: "root"
        }
    },
    persist: function() {
        Ext.data.cookies.set("auth", this.get("auth"));
    },
    destroy: function() {
        Ext.data.cookies.set("auth", null);
        this.set("sid", null);
        this.set("auth", null);
        this.set("user", null);
    },
    restore: function(b) {
        var a = Ext.data.cookies.get("auth");
        if (a) {
            this.request({
                method: "GET",
                url: this.getProxy().buildUrl({
                    operation: new Ext.data.Operation({
                        action: "read"
                    }),
                    url: "/proxy/auth/status"
                })
            }, b);
        } else {
            b(false);
        }
    },
    login: function(c, a, b) {
        this.request({
            method: "POST",
            url: this.getProxy().buildUrl({
                operation: new Ext.data.Operation({
                    action: "update"
                }),
                url: "/proxy/auth/login"
            }),
            params: {
                username: c,
                password: a
            }
        }, b);
    },
    register: function(d, b, a, c) {
        this.request({
            method: "POST",
            url: this.getProxy().buildUrl({
                operation: new Ext.data.Operation({
                    action: "create"
                }),
                url: "/proxy/auth/register"
            }),
            params: {
                username: d,
                password: b,
                email: a
            }
        }, c);
    },
    password: function(a, b) {
        this.request({
            method: "POST",
            url: this.getProxy().buildUrl({
                operation: new Ext.data.Operation({
                    action: "update"
                }),
                url: "/proxy/auth/password"
            }),
            params: {
                email: a
            }
        }, b);
    },
    settings: function(a, b) {
        this.request({
            method: "POST",
            url: this.getProxy().buildUrl({
                operation: new Ext.data.Operation({
                    action: "update"
                }),
                url: "/proxy/auth/settings"
            }),
            params: a
        }, b);
    },
    request: function(a, b) {
        Ext.Ajax.request(Ext.apply(a, {
            success: function(c, d) {
                var e = Ext.decode(c.responseText);
                if (e.success) {
                    if (e.sid) {
                        this.set("sid", e.sid);
                    }
                    if (e.user) {
                        this.set("user", e.user);
                    }
                    if (e.cookie) {
                        this.set("auth", e.cookie);
                        this.persist();
                    }
                    if (b) {
                        b(true);
                    }
                } else {
                    if (b) {
                        b(false, e.errors);
                    }
                }
            },
            failure: function(c) {
                data = Ext.decode(c.responseText);
                if (b) {
                    b(false);
                }
            },
            scope: this
        }));
    }
});

bandcast.models.User = Ext.regModel("User", {
    fields: [ {
        name: "id",
        type: "int"
    }, {
        name: "username",
        type: "string"
    }, {
        name: "displayname",
        type: "string"
    }, {
        name: "avatars",
        type: "auto"
    }, {
        name: "noavatar",
        type: "int"
    }, {
        name: "checkin",
        type: "auto"
    }, {
        name: "relationship",
        type: "auto"
    } ],
    associations: [ {
        type: "hasMany",
        model: "Activity",
        name: "activity",
        primaryKey: "id",
        foreignKey: "userid"
    } ],
    proxy: {
        type: "bandcast",
        url: "/proxy/users",
        id: "user",
        reader: {
            type: "json",
            root: "users"
        }
    }
});

bandcast.stores.User = new Ext.data.BandcastStore({
    storeId: "user",
    model: "User",
    loadByUsername: function(c, b) {
        var a = new Ext.data.Operation({
            action: "read",
            filters: [ new Ext.util.Filter({
                property: "username",
                value: c
            }) ]
        });
        this.getProxy().read(a, function(e) {
            var d = a.getRecords();
            this.loadRecords(d, true);
            if (b && typeof b == "function") {
                b(d);
            }
        }, this);
    }
});

bandcast.stores.Friend = new Ext.data.BandcastStore({
    storeId: "friend",
    model: "User",
    pageSize: 50,
    sorters: [ {
        property: "username",
        direction: "ASC"
    } ],
    addByQr: function(e, b, d) {
        var a = this.getProxy().buildUrl({
            operation: new Ext.data.Operation({
                action: "create"
            }),
            url: "/proxy/users"
        });
        var c = {
            username: e,
            qrcode: b
        };
        this.request(a, c, d);
    },
    addByUsername: function(d, c) {
        var a = this.getProxy().buildUrl({
            operation: new Ext.data.Operation({
                action: "create"
            }),
            url: "/proxy/users"
        });
        var b = {
            username: d,
            action: "add"
        };
        this.request(a, b, c);
    },
    approveByUsername: function(d, c) {
        var a = this.getProxy().buildUrl({
            operation: new Ext.data.Operation({
                action: "create"
            }),
            url: "/proxy/users"
        });
        var b = {
            username: d,
            action: "approve"
        };
        this.request(a, b, c);
    },
    denyByUsername: function(d, c) {
        var a = this.getProxy().buildUrl({
            operation: new Ext.data.Operation({
                action: "create"
            }),
            url: "/proxy/users"
        });
        var b = {
            username: d,
            action: "deny"
        };
        this.request(a, b, c);
    },
    request: function(a, b, c) {
        Ext.Ajax.request({
            method: "POST",
            url: a,
            params: b,
            success: function(d, e) {
                var f = Ext.decode(d.responseText);
                if (c) {
                    if (f.success) {
                        c(true);
                    } else {
                        c(false, f.errors);
                    }
                }
            },
            failure: function(d) {
                data = Ext.decode(d.responseText);
                if (c) {
                    c(false);
                }
            },
            scope: this
        });
    }
});

bandcast.stores.Request = new Ext.data.BandcastStore({
    storeId: "requests",
    model: "User",
    remoteFilter: true,
    pageSize: 50,
    sorters: [ {
        property: "username",
        direction: "ASC"
    } ],
    filters: [ {
        property: "relationship",
        value: "pending"
    } ]
});

bandcast.models.Activity = Ext.regModel("Activity", {
    fields: [ {
        name: "id",
        type: "int"
    }, {
        name: "activity",
        type: "string"
    }, {
        name: "type",
        type: "string"
    }, {
        name: "typeid",
        type: "int"
    }, {
        name: "recipient",
        type: "int"
    }, {
        name: "userid",
        type: "int"
    }, {
        name: "username",
        type: "string"
    }, {
        name: "displayname",
        type: "string"
    }, {
        name: "avatars",
        type: "auto"
    }, {
        name: "noavatar",
        type: "int"
    }, {
        name: "created",
        type: "date",
        dateFormat: "c"
    } ],
    associations: [ {
        type: "belongsTo",
        model: "User",
        name: "user",
        primaryKey: "userid",
        foreignKey: "id"
    } ],
    proxy: {
        type: "bandcast",
        url: "/proxy/activity",
        id: "activity",
        reader: {
            type: "json",
            root: "activities",
            totalProperty: "total",
            successProperty: "success"
        }
    }
});

bandcast.stores.Activity = new Ext.data.BandcastStore({
    storeId: "activityStore",
    model: "Activity",
    pageSize: 30,
    sorters: [ {
        property: "created",
        direction: "DESC"
    } ]
});

bandcast.models.Event = Ext.regModel("Event", {
    fields: [ {
        name: "id",
        type: "int"
    }, {
        name: "name",
        type: "string"
    }, {
        name: "urlkey",
        type: "string"
    }, {
        name: "started",
        type: "date",
        dateFormat: "c"
    }, {
        name: "ended",
        type: "date",
        dateFormat: "c"
    }, {
        name: "artists",
        type: "auto"
    }, {
        name: "venues",
        type: "auto"
    }, {
        name: "venue",
        type: "string"
    } ],
    proxy: {
        type: "bandcast",
        url: "/proxy/event",
        id: "id",
        reader: {
            type: "json",
            root: "events"
        }
    }
});

bandcast.stores.Event = new Ext.data.BandcastStore({
    storeId: "event",
    model: "Event",
    pageSize: 250,
    sortBy: null,
    sorters: [ {
        property: "name",
        direction: "ASC"
    } ],
    getGroupString: function(a) {
        switch (this.sortBy) {
          case "venue":
            return a.get("venue");
          case "time":
            return a.get("started").toLocaleDateString();
          case "alpha":
          default:
            return a.get("name")[0];
        }
    },
    sortAlpha: function() {
        this.sortBy = "alpha";
        this.sort("name", "ASC");
    },
    sortVenue: function() {
        this.sortBy = "venue";
        this.sort("started", "ASC");
        this.sort("venue", "ASC");
    },
    sortTime: function() {
        this.sortBy = "time";
        this.sort("started", "ASC");
    }
});

bandcast.stores.Event.addListener("afterload", function(b, a, c) {
    if (c) {
        bandcast.stores.Artist.removeAll();
        bandcast.stores.Venue.removeAll();
        this.each(function(e) {
            var h = e.get("venues"), f, d, g = "";
            for (f = 0, d = h.length; f < d; f++) {
                if (!bandcast.stores.Venue.getById(parseInt(h[f].id, 10))) {
                    bandcast.stores.Venue.add(h[f]);
                }
                g = g.length ? g + ", " + h[f].name : h[f].name;
            }
            e.set("venue", g ? g : "TBA");
        });
    }
});

bandcast.models.Artist = Ext.regModel("Artist", {
    fields: [ {
        name: "id",
        type: "int"
    }, {
        name: "name",
        type: "string"
    }, {
        name: "urlkey",
        type: "string"
    }, {
        name: "description",
        type: "string"
    }, {
        name: "metadata",
        type: "auto"
    }, {
        name: "updated",
        type: "date",
        dateFormat: "c"
    } ],
    proxy: {
        type: "bandcast",
        url: "/proxy/artist",
        id: "id",
        reader: {
            type: "json",
            root: "artists"
        }
    }
});

bandcast.stores.Artist = new Ext.data.Store({
    storeId: "artist",
    model: "Artist",
    pageSize: 500,
    sorters: [ {
        property: "name",
        direction: "ASC"
    } ]
});

bandcast.models.Venue = Ext.regModel("Venue", {
    fields: [ {
        name: "id",
        type: "int"
    }, {
        name: "name",
        type: "string"
    }, {
        name: "urlkey",
        type: "string"
    }, {
        name: "address",
        type: "string"
    }, {
        name: "city",
        type: "string"
    }, {
        name: "state",
        type: "string"
    }, {
        name: "zip",
        type: "string"
    }, {
        name: "countryid",
        type: "int"
    }, {
        name: "latitude",
        type: "float"
    }, {
        name: "longitude",
        type: "float"
    } ],
    proxy: {
        type: "bandcast",
        url: "/proxy/venue",
        id: "id",
        reader: {
            type: "json",
            root: "venues"
        }
    }
});

bandcast.stores.Venue = new Ext.data.Store({
    storeId: "venue",
    model: "Venue",
    pageSize: 50,
    sorters: [ {
        property: "name",
        direction: "ASC"
    } ]
});

bandcast.models.Schedule = Ext.regModel("Schedule", {
    fields: [ {
        name: "id",
        type: "int"
    }, {
        name: "name",
        type: "string"
    }, {
        name: "urlkey",
        type: "string"
    }, {
        name: "started",
        type: "date",
        dateFormat: "c"
    }, {
        name: "users",
        type: "auto"
    }, {
        name: "yes",
        type: "int"
    }, {
        name: "maybe",
        type: "int"
    } ],
    proxy: {
        type: "bandcast",
        url: "/proxy/schedule",
        id: "schedule",
        reader: {
            type: "json",
            root: "events",
            totalProperty: "total",
            successProperty: "success"
        }
    }
});

bandcast.stores.Schedule = new Ext.data.BandcastStore({
    storeId: "scheduleStore",
    model: "Schedule",
    pageSize: 200,
    sorters: [ {
        property: "started",
        direction: "ASC"
    } ],
    getGroupString: function(a) {
        var b = bandcast.timezoned(a.get("started"));
        return b.format(bandcast.config.event.date.format.timelong);
    }
});

bandcast.models.Checkin = Ext.regModel("Checkin", {
    fields: [ {
        name: "id",
        type: "int"
    }, {
        name: "userid",
        type: "int"
    }, {
        name: "type",
        type: "string"
    }, {
        name: "typeid",
        type: "int"
    }, {
        name: "attending",
        type: "int"
    }, {
        name: "checkin",
        type: "date",
        dateFormat: "c"
    }, {
        name: "checkout",
        type: "date",
        dateFormat: "c"
    }, {
        name: "created",
        type: "date",
        dateFormat: "c"
    } ],
    associations: [ {
        type: "belongsTo",
        model: "User",
        name: "user",
        primaryKey: "userid",
        foreignKey: "id"
    } ],
    proxy: {
        type: "bandcast",
        url: "/proxy/checkin",
        id: "checkin",
        reader: {
            type: "json",
            root: "checkins",
            totalProperty: "total",
            successProperty: "success"
        }
    }
});

bandcast.views.Login = Ext.extend(Ext.Panel, {
    initComponent: function() {
        if (!Ext.getCmp("loginform")) {
            var a = {
                id: "loginform",
                scroll: "vertical",
                listeners: {
                    beforesubmit: function(c, b) {
                        Ext.dispatch({
                            controller: "auth",
                            action: "loginAction",
                            form: c,
                            values: b
                        });
                        return false;
                    }
                },
                items: [ {
                    xtype: "fieldset",
                    title: "log in to " + bandcast.config.defaults.title,
                    defaults: {
                        labelAlign: "left",
                        labelWidth: "40%"
                    },
                    items: [ {
                        xtype: "textfield",
                        name: "username",
                        label: "Username",
                        useClearIcon: true,
                        autoCapitalize: false
                    }, {
                        xtype: "passwordfield",
                        name: "password",
                        label: "Password",
                        useClearIcon: false
                    } ]
                }, {
                    xtype: "button",
                    text: "Log in",
                    scope: this,
                    formBind: true,
                    handler: function(b) {
                        form.submit();
                    }
                } ],
                dockedItems: [ {
                    xtype: "toolbar",
                    dock: "bottom",
                    ui: "gray",
                    items: [ {
                        text: "Forgot password",
                        handler: function() {
                            form.destroy();
                            Ext.dispatch({
                                controller: "auth",
                                action: "password"
                            });
                        }
                    }, {
                        xtype: "spacer"
                    }, {
                        text: "Create an account",
                        ui: "confirm",
                        handler: function() {
                            form.destroy();
                            Ext.dispatch({
                                controller: "auth",
                                action: "register"
                            });
                        }
                    } ]
                } ]
            };
            if (Ext.is.Phone) {
                Ext.apply(a, {
                    fullscreen: true,
                    modal: false
                });
            } else {
                Ext.apply(a, {
                    autoRender: true,
                    floating: true,
                    modal: true,
                    centered: true,
                    hideOnMaskTap: false,
                    height: 385,
                    width: 440
                });
            }
            form = new Ext.form.FormPanel(a);
            form.show();
        }
        bandcast.views.Login.superclass.initComponent.apply(this, arguments);
    }
});

Ext.reg("bandcast.views.Login", bandcast.views.Login);

bandcast.views.Password = Ext.extend(Ext.Panel, {
    initComponent: function() {
        if (!Ext.getCmp("passwordform")) {
            var a = {
                id: "passwordform",
                scroll: "vertical",
                listeners: {
                    beforesubmit: function(c, b) {
                        Ext.dispatch({
                            controller: "auth",
                            action: "passwordAction",
                            form: c,
                            values: b
                        });
                        return false;
                    }
                },
                items: [ {
                    xtype: "fieldset",
                    title: "reset your password",
                    defaults: {
                        labelAlign: "left",
                        labelWidth: "40%"
                    },
                    items: [ {
                        xtype: "textfield",
                        name: "email",
                        label: "Email",
                        useClearIcon: true,
                        autoCapitalize: false
                    } ]
                }, {
                    xtype: "button",
                    text: "Reset password",
                    scope: this,
                    formBind: true,
                    handler: function(b) {
                        form.submit();
                    }
                } ],
                dockedItems: [ {
                    xtype: "toolbar",
                    dock: "bottom",
                    ui: "gray",
                    items: [ {
                        text: "Remembered it",
                        handler: function() {
                            form.destroy();
                            Ext.dispatch({
                                controller: "auth",
                                action: "login"
                            });
                        }
                    }, {
                        xtype: "spacer"
                    }, {
                        text: "Create an account",
                        ui: "confirm",
                        handler: function() {
                            form.destroy();
                            Ext.dispatch({
                                controller: "auth",
                                action: "register"
                            });
                        }
                    } ]
                } ]
            };
            if (Ext.is.Phone) {
                Ext.apply(a, {
                    fullscreen: true,
                    modal: false
                });
            } else {
                Ext.apply(a, {
                    autoRender: true,
                    floating: true,
                    modal: true,
                    centered: true,
                    hideOnMaskTap: false,
                    height: 385,
                    width: 440
                });
            }
            form = new Ext.form.FormPanel(a);
            form.show();
        }
        bandcast.views.Password.superclass.initComponent.apply(this, arguments);
    }
});

Ext.reg("bandcast.views.Password", bandcast.views.Password);

bandcast.views.Register = Ext.extend(Ext.Panel, {
    initComponent: function() {
        if (!Ext.getCmp("registerform")) {
            var a = {
                id: "registerform",
                scroll: "vertical",
                listeners: {
                    beforesubmit: function(c, b) {
                        Ext.dispatch({
                            controller: "auth",
                            action: "registerAction",
                            form: c,
                            values: b
                        });
                        return false;
                    }
                },
                items: [ {
                    xtype: "fieldset",
                    title: "sign up for " + bandcast.config.defaults.title,
                    defaults: {
                        labelAlign: "left",
                        labelWidth: "40%"
                    },
                    items: [ {
                        xtype: "textfield",
                        name: "email",
                        label: "Email",
                        useClearIcon: true,
                        autoCapitalize: false
                    }, {
                        xtype: "textfield",
                        name: "username",
                        label: "Username",
                        useClearIcon: true,
                        autoCapitalize: false
                    }, {
                        xtype: "passwordfield",
                        name: "password",
                        label: "Password",
                        useClearIcon: false
                    } ]
                }, {
                    xtype: "button",
                    text: "Create account",
                    scope: this,
                    formBind: true,
                    handler: function(b) {
                        form.submit();
                    }
                } ],
                dockedItems: [ {
                    xtype: "toolbar",
                    dock: "bottom",
                    ui: "gray",
                    items: [ {
                        text: "Forgot password",
                        handler: function() {
                            form.destroy();
                            Ext.dispatch({
                                controller: "auth",
                                action: "password"
                            });
                        }
                    }, {
                        xtype: "spacer"
                    }, {
                        text: "Have an account?",
                        ui: "gray",
                        handler: function() {
                            form.destroy();
                            Ext.dispatch({
                                controller: "auth",
                                action: "login"
                            });
                        }
                    } ]
                } ]
            };
            if (Ext.is.Phone) {
                Ext.apply(a, {
                    fullscreen: true,
                    modal: false
                });
            } else {
                Ext.apply(a, {
                    autoRender: true,
                    floating: true,
                    modal: true,
                    centered: true,
                    hideOnMaskTap: false,
                    height: 385,
                    width: 440
                });
            }
            form = new Ext.form.FormPanel(a);
            form.show();
        }
        bandcast.views.Register.superclass.initComponent.apply(this, arguments);
    }
});

Ext.reg("bandcast.views.Register", bandcast.views.Register);

bandcast.views.UserDetail = Ext.extend(Ext.Panel, {
    id: "userdetail",
    layout: "card",
    initComponent: function() {
        var a = Ext.getCmp(this.id);
        if (a) {
            if (a.prevCard) {
                a.ownerCt.setActiveItem(a.prevCard);
            }
            a.destroy();
        }
        this.toolbar = new Ext.Toolbar({
            items: [ {
                ui: "back",
                text: "Back",
                scope: this,
                handler: function() {
                    Ext.History.add(this.prevUrl);
                    this.ownerCt.setActiveItem(this.prevCard, {
                        type: "slide",
                        reverse: true,
                        scope: this,
                        after: function() {
                            this.destroy();
                        }
                    });
                }
            }, {
                xtype: "spacer",
                flex: 1
            } ]
        });
        this.wrapper = new Ext.Panel({
            layout: "fit",
            dockedItems: [ this.toolbar ]
        });
        if (this.user) {
            this.toolbar.setTitle(this.user.get("username").toLowerCase());
            this.wrapper.addDocked({
                id: "userinfo",
                styleHtmlContent: true,
                tpl: new Ext.XTemplate('<div class="detail">', '<div class="avatar"><tpl if="noavatar == 0 && avatars"><img src="{avatars.thumb}" width="45" height="45" alt="{username}" /></tpl></div>', '<div class="blurb">', '<div class="primary">{displayname}</div>', '<tpl if="self == false && loaded == true && friend == true">', '<div class="secondary">{displayname} is your friend</div>', "</tpl>", '<tpl if="self == false && loaded == true && friend == false">', '<div class="secondary">{displayname} is not your friend</div>', "</tpl>", '<tpl if="self == false && loaded == false">', '<div class="secondary">Loading relationship ...</div>', "</tpl>", '<tpl if="self == true">', '<div class="secondary">This is you!</div>', "</tpl>", "</div>", "</div>"),
                data: Ext.apply(this.user.data, {
                    friend: this.friend,
                    loaded: this.loaded,
                    self: this.user.get("username") == Ext.data.auth.get("user").username
                })
            });
            this.wrapper.doLayout();
        }
        Ext.apply(this, {
            items: [ this.wrapper ]
        });
        bandcast.views.UserDetail.superclass.initComponent.call(this);
    },
    buildList: function() {
        this.list = new Ext.List({
            store: this.user.activity(),
            loadingText: "Loading",
            plugins: [ {
                ptype: "pullrefresh",
                pullRefreshText: "Pull down to refresh",
                releaseRefreshText: "Release to refresh",
                loadingText: "Loading..."
            } ],
            itemTpl: new Ext.XTemplate('<tpl for=".">', '<div class="primary">{activity:this.unlink}</div>', '<div class="secondary">{created:this.timeago}</div>', "</tpl>", {
                unlink: function(a) {
                    return a.replace(/(<a ([^>]+)>)/ig, "");
                },
                timeago: function(a) {
                    return bandcast.timeago(a, true);
                }
            }),
            listeners: {
                afterrender: {
                    fn: function(a) {
                        a.store.load();
                    },
                    scope: this
                }
            }
        });
        this.wrapper.add(this.list);
        this.wrapper.doComponentLayout();
    },
    allowFriend: function() {
        this.toolbar.add({
            ui: "button",
            iconCls: "user_add",
            iconMask: true,
            scope: this,
            handler: function(a, b) {
                Ext.dispatch({
                    controller: "friend",
                    action: "addAction",
                    username: this.user.get("username")
                });
            }
        });
        this.wrapper.doComponentLayout();
        this.toolbar.doComponentLayout();
    },
    allowMessage: function() {
        this.toolbar.add({
            ui: "button",
            iconCls: "compose",
            iconMask: true,
            scope: this,
            handler: function(a, b) {
                Ext.dispatch({
                    controller: "activity",
                    action: "add",
                    prevCard: this.wrapper,
                    parent: this,
                    recipient: this.user.get("username")
                });
            }
        });
        this.toolbar.doComponentLayout();
    },
    invalidUser: function() {
        this.toolbar.setTitle("invalid user");
        this.wrapper.remove(Ext.getCmp("userinfo"));
    }
});

Ext.reg("bandcast.views.UserDetail", bandcast.views.UserDetail);

bandcast.views.ActivityAdd = Ext.extend(Ext.form.FormPanel, {
    id: "activityadd",
    initComponent: function() {
        var e = Ext.getCmp(this.id);
        if (e) {
            if (e.prevCard) {
                e.ownerCt.setActiveItem(e.prevCard);
            }
            e.destroy();
        }
        if (this.recipient) {
            var f = "message", a = "Send a private message to " + this.recipient + ". You must be friends for the message to be received.", c = "Send message";
        } else {
            var f = "broadcast", a = "Tell your friends what you're doing, where you are, what you recommend, etc.", c = "Tell my friends";
        }
        var d = new Ext.Toolbar({
            title: f,
            items: [ {
                ui: "back",
                text: "Back",
                scope: this,
                handler: function() {
                    this.goBack();
                }
            } ]
        });
        var b = [ {
            xtype: "fieldset",
            instructions: a,
            items: [ {
                xtype: "textareafield",
                name: "status",
                maxLength: 140,
                maxRows: 4,
                useClearIcon: true
            } ]
        }, {
            xtype: "button",
            text: c,
            scope: this,
            formBind: true,
            handler: function(g) {
                this.submit();
            }
        } ];
        Ext.apply(this, {
            dockedItems: d,
            items: b,
            scope: this,
            listeners: {
                beforesubmit: function(h, g) {
                    if (g.status) {
                        Ext.dispatch({
                            controller: "activity",
                            action: "addAction",
                            form: h,
                            values: Ext.apply(g, {
                                recipient: this.recipient
                            })
                        });
                        this.goBack();
                    } else {
                        Ext.Msg.alert("Missing message", "Whoops! You forgot to post your message.", Ext.emptyFn);
                    }
                    return false;
                }
            }
        });
        bandcast.views.ActivityAdd.superclass.initComponent.call(this);
    },
    goBack: function() {
        this.ownerCt.setActiveItem(this.prevCard, {
            type: "slide",
            reverse: true,
            scope: this,
            after: function() {
                this.destroy();
            }
        });
    }
});

Ext.reg("bandcast.views.ActivityAdd", bandcast.views.ActivityAdd);

bandcast.views.ActivityList = Ext.extend(Ext.Panel, {
    id: "activitylist",
    layout: "card",
    historyUrl: "activity/list",
    initComponent: function() {
        this.buttons = new Ext.SegmentedButton({
            defaults: {
                flex: 1
            },
            items: [ {
                text: bandcast.config.aliases.event.single + " check in",
                scope: this,
                handler: function(a, b) {
                    Ext.dispatch({
                        controller: "event",
                        action: "checkin",
                        btn: a,
                        callback: function() {
                            a.removeCls(a.pressedCls);
                        }
                    });
                }
            }, {
                text: bandcast.config.aliases.venue.single + " check in",
                scope: this,
                handler: function(a, b) {
                    Ext.dispatch({
                        controller: "venue",
                        action: "checkin",
                        btn: a,
                        callback: function() {
                            a.removeCls(a.pressedCls);
                        }
                    });
                }
            } ],
            layout: {
                pack: "center"
            },
            style: {
                width: "100%",
                fontSize: "80%"
            }
        });
        this.wrapper = new Ext.Panel({
            layout: "fit",
            items: this.buildList(),
            dockedItems: [ {
                xtype: "toolbar",
                title: "activity stream",
                items: [ {
                    xtype: "spacer",
                    flex: 1
                }, {
                    ui: "button",
                    iconCls: "compose",
                    iconMask: true,
                    scope: this,
                    handler: function(a, b) {
                        Ext.dispatch({
                            controller: "activity",
                            action: "add",
                            prevCard: this.wrapper,
                            parent: this
                        });
                    }
                } ]
            }, {
                xtype: "toolbar",
                ui: "light",
                items: this.buttons,
                layout: {
                    pack: "center"
                }
            } ]
        });
        Ext.apply(this, {
            items: [ this.wrapper ]
        });
        bandcast.views.ActivityList.superclass.initComponent.call(this);
    },
    buildList: function() {
        this.list = new Ext.List({
            store: bandcast.stores.Activity,
            loadingText: "Loading",
            plugins: [ {
                ptype: "pullrefresh",
                pullRefreshText: "Pull down to refresh",
                releaseRefreshText: "Release to refresh",
                loadingText: "Loading..."
            } ],
            itemTpl: new Ext.XTemplate('<tpl for=".">', '<div class="avatar"><tpl if="noavatar == 0 && avatars"><img src="{avatars.thumb}" width="45" height="45" alt="{username}" /></tpl></div>', '<div class="primary">{activity}</div>', '<div class="secondary">{created:this.timeago}</div>', "</tpl>", {
                timeago: function(a) {
                    if (a) {
                        return bandcast.timeago(a, true);
                    } else {
                        return "pending";
                    }
                }
            }),
            listeners: {
                click: {
                    element: "el",
                    delegate: "a",
                    stopEvent: true,
                    fn: function(b, a) {
                        if (this.delayedTask != null) {
                            this.delayedTask.cancel();
                            this.delayedTask = null;
                        }
                        this.linkHandler(b, a);
                    },
                    scope: this
                },
                itemtap: {
                    fn: function(a, b, d, c) {
                        a.getSelectionModel().deselectAll();
                        if (this.delayedTask == null) {
                            this.delayedTask = new Ext.util.DelayedTask(function() {
                                var e = a.getSelectionModel();
                                e.select(b);
                                (new Ext.util.DelayedTask(function() {
                                    a.getSelectionModel().deselectAll();
                                }, this)).delay(400);
                                this.showUser(a.getSelectedRecords()[0].data.username);
                                this.delayedTask = null;
                            }, this);
                        }
                        this.delayedTask.delay(200);
                    },
                    scope: this
                },
                afterrender: {
                    fn: function(a) {
                        a.setLoading(true);
                        a.store.load();
                    },
                    scope: this
                }
            }
        });
        return this.list;
    },
    linkHandler: function(h, b) {
        var g = h.getTarget(), d = g.outerHTML, c = /data-([^=]*)="([^"]*)"/g, f = {}, a;
        while (a = c.exec(d)) {
            f[a[1]] = a[2];
        }
        switch (f.type) {
          case "user":
            this.showUser(f.username);
            break;
          case "event":
            this.showEvent(f.event);
            break;
          case "venue":
            this.showVenue(f.venue);
            break;
          case "artist":
            this.showArtist(f.artist);
            break;
        }
    },
    showUser: function(a) {
        Ext.dispatch({
            controller: "user",
            action: "detail",
            historyUrl: "user/-/" + a,
            prevCard: this.wrapper,
            prevUrl: this.historyUrl,
            username: a,
            parent: this
        });
    },
    showEvent: function(a) {
        Ext.dispatch({
            controller: "event",
            action: "detail",
            historyUrl: "event/-/" + a,
            prevCard: this.wrapper,
            prevUrl: this.historyUrl,
            event: a,
            parent: this
        });
    },
    showVenue: function(a) {
        Ext.dispatch({
            controller: "venue",
            action: "detail",
            historyUrl: "venue/-/" + a,
            prevCard: this.wrapper,
            prevUrl: this.historyUrl,
            venue: a,
            parent: this
        });
    },
    showArtist: function(a) {
        Ext.dispatch({
            controller: "artist",
            action: "detail",
            historyUrl: "artist/-/" + a,
            prevCard: this.wrapper,
            prevUrl: this.historyUrl,
            artist: a,
            parent: this
        });
    }
});

Ext.reg("bandcast.views.ActivityList", bandcast.views.ActivityList);

bandcast.views.EventList = Ext.extend(Ext.Panel, {
    id: "eventlist",
    layout: "card",
    historyUrl: "event/list",
    listeners: {
        activate: function() {
            bandcast.stores.Event.clearFilter();
            var a = this.buttons.getPressed();
            if (a && a.sort) {
                bandcast.stores.Event["sort" + a.sort]();
            }
        }
    },
    initComponent: function() {
        this.buttons = new Ext.SegmentedButton({
            defaults: {
                flex: 1
            },
            listeners: {
                afterlayout: function() {
                    this.setPressed(0, true, false);
                }
            },
            items: [ {
                text: "alphabetical",
                sort: "Alpha",
                scope: this,
                handler: function(a, b) {
                    this.list.store.sortAlpha();
                    if (this.list.indexBar && this.list.indexBar.id) {
                        Ext.getCmp(this.list.indexBar.id).show();
                    }
                }
            }, {
                text: "by " + bandcast.config.aliases.venue.single,
                sort: "Venue",
                scope: this,
                handler: function(a, b) {
                    this.list.store.sortVenue();
                    if (this.list.indexBar && this.list.indexBar.id) {
                        Ext.getCmp(this.list.indexBar.id).hide();
                    }
                }
            }, {
                text: "by time",
                sort: "Time",
                scope: this,
                handler: function(a, b) {
                    this.list.store.sortTime();
                    if (this.list.indexBar && this.list.indexBar.id) {
                        Ext.getCmp(this.list.indexBar.id).hide();
                    }
                }
            } ],
            layout: {
                pack: "center"
            },
            style: {
                width: "100%",
                fontSize: "80%"
            }
        });
        this.wrapper = new Ext.Panel({
            layout: "fit",
            items: this.buildList(),
            dockedItems: [ {
                xtype: "toolbar",
                title: "the " + bandcast.config.aliases.event.plural
            }, {
                xtype: "toolbar",
                ui: "light",
                items: this.buttons,
                layout: {
                    pack: "center"
                }
            } ]
        });
        Ext.apply(this, {
            items: [ this.wrapper ]
        });
        bandcast.views.EventList.superclass.initComponent.call(this);
    },
    buildList: function() {
        this.list = new Ext.List({
            store: bandcast.stores.Event,
            grouped: true,
            indexBar: Ext.is.Phone,
            loadingText: "Loading",
            itemTpl: new Ext.XTemplate('<tpl for=".">', '<div class="primary">{name}</div>', '<div class="secondary">{started:this.date} @ {venue}</div>', "</tpl>", {
                date: function(a) {
                    var b = bandcast.timezoned(a);
                    return b.format(bandcast.config.event.date.format.timeshort);
                },
                compiled: true
            }),
            listeners: {
                itemtap: {
                    fn: function(a, b, c, d) {
                        this.showEvent(a.store.getAt(b).data.urlkey);
                        (new Ext.util.DelayedTask(function() {
                            a.getSelectionModel().deselectAll();
                        }, this)).delay(700);
                    },
                    scope: this
                },
                afterrender: {
                    fn: function(a) {
                        if (!this.list.store.getCount()) {
                            a.setLoading(true);
                            a.store.load();
                        }
                    },
                    scope: this
                }
            }
        });
        return this.list;
    },
    showEvent: function(a) {
        Ext.dispatch({
            controller: "event",
            action: "detail",
            historyUrl: "event/-/" + a,
            prevCard: this.wrapper,
            prevUrl: this.historyUrl,
            event: a,
            parent: this
        });
    }
});

Ext.reg("bandcast.views.EventList", bandcast.views.EventList);

bandcast.views.EventCheckin = Ext.extend(Ext.Sheet, {
    id: "eventcheckin",
    hideOnMaskTap: true,
    checked: null,
    scroll: "vertical",
    stretchX: true,
    stretchY: true,
    initComponent: function() {
        Ext.apply(this, {
            items: {
                xtype: "fieldset",
                cls: "radio-checkin",
                defaults: {
                    xtype: "radiofield",
                    labelWidth: "100%",
                    listeners: {
                        render: function(a) {
                            if (a.labelEl) {
                                a.labelEl.on("click", function() {
                                    a.setChecked(true);
                                }, a);
                            }
                        },
                        check: {
                            fn: function(a) {
                                this.checked = a;
                            },
                            scope: this
                        }
                    }
                },
                items: this.getEvents()
            },
            dockedItems: {
                xtype: "button",
                text: "Check in",
                ui: "action",
                dock: "bottom",
                scope: this,
                handler: function(a, b) {
                    Ext.dispatch({
                        controller: "event",
                        action: "checkinAction",
                        id: this.checked.value,
                        name: this.checked.label
                    });
                    a.up().destroy();
                    return false;
                }
            },
            listeners: {
                hide: function(a) {
                    if (typeof this.callback == "function") {
                        a.destroy();
                        this.callback();
                    }
                }
            }
        });
        bandcast.views.EventCheckin.superclass.initComponent.apply(this, arguments);
    },
    getEvents: function() {
        var a = Ext.getStore("event"), b = [];
        if (a) {
            a.clearFilter();
            a.sort("name", "ASC");
            a.each(function(c) {
                b.push({
                    name: "event",
                    label: c.get("name"),
                    value: c.get("id")
                });
            });
        }
        return b;
    },
    alignTo: function(a, c, b) {
        b -= 10;
        bandcast.views.EventCheckin.superclass.alignTo.apply(this, [ a, c, b ]);
    }
});

Ext.reg("bandcast.views.EventCheckin", bandcast.views.EventCheckin);

bandcast.views.EventDetail = Ext.extend(Ext.Panel, {
    id: "eventdetail",
    scroll: "vertical",
    initComponent: function() {
        var a = Ext.getCmp(this.id);
        if (a) {
            if (a.prevCard) {
                a.ownerCt.setActiveItem(a.prevCard);
            }
            a.destroy();
        }
        this.toolbar = new Ext.Toolbar({
            items: [ {
                ui: "back",
                text: "Back",
                scope: this,
                handler: function() {
                    Ext.History.add(this.prevUrl);
                    this.ownerCt.setActiveItem(this.prevCard, {
                        type: "slide",
                        reverse: true,
                        scope: this,
                        after: function() {
                            this.destroy();
                        }
                    });
                }
            } ]
        });
        if (this.event) {
            this.toolbar.setTitle(this.event.get("name").toLowerCase());
            Ext.apply(this, {
                items: [ {
                    styleHtmlContent: true,
                    tpl: new Ext.XTemplate('<div class="detail">', '<div class="avatar"><tpl if="metadata && metadata.images"><img src="{metadata.images.thumb}" width="45" height="45" alt="{name}" /></tpl></div>', '<div class="blurb">', '<div class="primary">{name}</div>', '<div class="secondary">{venue}, {started:this.date} - {ended:this.date}</div>', "</div>", "</div>", {
                        date: function(b) {
                            var d = new Date(b.getTime());
                            if (typeof bandcast.config.event.date.timezone != "undefined") {
                                var c = b.getTimezoneOffset() + bandcast.config.event.date.timezone * 60;
                                d.setTime(b.getTime() + c * 6e4);
                            }
                            return d.format(bandcast.config.event.date.format.timeshort);
                        },
                        compiled: true
                    }),
                    data: this.event.data
                } ]
            });
            this.addArtists(this.event.get("artists"));
        }
        Ext.apply(this, {
            dockedItems: [ this.toolbar, this.buildCheckin() ]
        });
        this.buildCheckin();
        bandcast.views.EventDetail.superclass.initComponent.call(this);
    },
    buildCheckin: function() {
        return new Ext.Toolbar({
            xtype: "toolbar",
            ui: "light",
            layout: {
                pack: "center"
            },
            items: new Ext.SegmentedButton({
                defaults: {
                    flex: 1
                },
                items: [ {
                    text: "I'm going",
                    scope: this,
                    handler: function(a, b) {
                        Ext.dispatch({
                            controller: "event",
                            action: "rsvpAction",
                            eventid: this.event.get("id"),
                            value: 2,
                            btn: a
                        });
                    }
                }, {
                    text: "Not going",
                    scope: this,
                    handler: function(a, b) {
                        Ext.dispatch({
                            controller: "event",
                            action: "rsvpAction",
                            eventid: this.event.get("id"),
                            value: 0,
                            btn: a
                        });
                    }
                } ],
                layout: {
                    pack: "center"
                },
                style: {
                    width: "100%",
                    fontSize: "80%"
                }
            })
        });
    },
    addArtists: function(a) {
        var c = a ? a.length : 0;
        if (c) {
            for (var b = 0; b < c; b++) {
                if (c > 1) {
                    this.items.push({
                        xtype: "toolbar",
                        title: a[b].name,
                        ui: "gray",
                        cls: "small_title"
                    });
                }
                this.items.push({
                    styleHtmlContent: true,
                    tpl: new Ext.XTemplate('<div id="artist-{id}" class="description">{id:this.description}</div>', {
                        description: function(e) {
                            var d = bandcast.stores.Artist.getById(e);
                            return d ? d.get("description") : "Loading ...";
                        }
                    }),
                    data: a[b]
                });
            }
        }
    }
});

Ext.reg("bandcast.views.EventDetail", bandcast.views.EventDetail);

bandcast.views.FriendList = Ext.extend(Ext.Panel, {
    id: "friendlist",
    layout: "card",
    historyUrl: "friend/list",
    initComponent: function() {
        this.wrapper = new Ext.Panel({
            layout: "fit",
            items: this.buildList(),
            dockedItems: [ {
                xtype: "toolbar",
                title: "my friends",
                items: [ {
                    ui: "button",
                    iconCls: "inbox2",
                    iconMask: true,
                    scope: this,
                    badgeText: bandcast.stores.Request.getCount(),
                    handler: function(a, b) {
                        Ext.dispatch({
                            controller: "friend",
                            action: "requests",
                            historyUrl: "friend/requests",
                            prevCard: this.wrapper,
                            parent: this
                        });
                    }
                }, {
                    xtype: "spacer",
                    flex: 1
                }, {
                    ui: "button",
                    iconCls: "search",
                    iconMask: true,
                    scope: this,
                    handler: function(a, b) {
                        Ext.dispatch({
                            controller: "friend",
                            action: "search",
                            historyUrl: "friend/search",
                            prevCard: this.wrapper,
                            parent: this
                        });
                    }
                } ]
            } ]
        });
        Ext.apply(this, {
            items: [ this.wrapper ]
        });
        bandcast.views.FriendList.superclass.initComponent.call(this);
    },
    buildList: function() {
        this.list = new Ext.List({
            store: bandcast.stores.Friend,
            loadingText: "Loading",
            plugins: [ {
                ptype: "pullrefresh",
                pullRefreshText: "Pull down to refresh",
                releaseRefreshText: "Release to refresh",
                loadingText: "Loading..."
            } ],
            itemTpl: new Ext.XTemplate('<tpl for=".">', '<div class="avatar"><tpl if="noavatar == 0"><img src="{avatars.thumb}" width="45" height="45" alt="{username}" /></tpl></div>', '<div class="primary">{displayname}</div>', '<div class="secondary">{checkin:this.location}</div>', "</tpl>", {
                location: function(b) {
                    if (b && !b.checkout) {
                        switch (b.type) {
                          case "event":
                            var a = bandcast.stores.Event.getById(b.typeid);
                            if (a) {
                                return a.get("name") + " (" + bandcast.timeago(b.checkin, true) + " ago)";
                            }
                            break;
                          case "venue":
                            var c = bandcast.stores.Venue.getById(b.typeid);
                            if (c) {
                                return c.get("name") + " (" + bandcast.timeago(b.checkin, true) + " ago)";
                            }
                            break;
                        }
                    }
                    return "off the grid";
                }
            }),
            listeners: {
                itemtap: {
                    fn: function(a, b, c, d) {
                        this.showUser(a.store.getAt(b).data.username);
                        (new Ext.util.DelayedTask(function() {
                            a.getSelectionModel().deselectAll();
                        }, this)).delay(700);
                    },
                    scope: this
                },
                afterrender: {
                    fn: function(a) {
                        a.setLoading(true);
                        a.store.load();
                    },
                    scope: this
                }
            }
        });
        return this.list;
    },
    showUser: function(a) {
        Ext.dispatch({
            controller: "user",
            action: "detail",
            historyUrl: "user/-/" + a,
            prevCard: this.wrapper,
            prevUrl: this.historyUrl,
            username: a,
            parent: this
        });
    }
});

Ext.reg("bandcast.views.FriendList", bandcast.views.FriendList);

bandcast.views.FriendRequests = Ext.extend(Ext.Panel, {
    id: "friendrequests",
    layout: "card",
    historyUrl: "friend/requests",
    initComponent: function() {
        this.toolbar = new Ext.Toolbar({
            title: "friend requests",
            items: [ {
                ui: "back",
                text: "Back",
                scope: this,
                handler: function() {
                    this.ownerCt.setActiveItem(this.prevCard, {
                        type: "slide",
                        reverse: true,
                        scope: this,
                        after: function() {
                            this.destroy();
                        }
                    });
                }
            } ]
        });
        Ext.apply(this, {
            dockedItems: this.toolbar,
            items: this.buildList()
        });
        bandcast.views.FriendList.superclass.initComponent.call(this);
    },
    buildList: function() {
        this.list = new Ext.List({
            store: bandcast.stores.Request,
            loadingText: "Loading",
            plugins: [ {
                ptype: "pullrefresh",
                pullRefreshText: "Pull down to refresh",
                releaseRefreshText: "Release to refresh",
                loadingText: "Loading..."
            } ],
            itemTpl: new Ext.XTemplate('<tpl for=".">', '<div class="avatar"><tpl if="noavatar == 0"><img src="{avatars.thumb}" width="45" height="45" alt="{username}" /></tpl></div>', '<div class="primary">{displayname}</div>', "</tpl>"),
            listeners: {
                itemtap: {
                    fn: function(a, b, c, d) {
                        this.showPrompt(a.store.getAt(b).data.username);
                        (new Ext.util.DelayedTask(function() {
                            a.getSelectionModel().deselectAll();
                        }, this)).delay(700);
                    },
                    scope: this
                },
                afterrender: {
                    fn: function(a) {
                        a.setLoading(true);
                        a.store.load();
                    },
                    scope: this
                }
            }
        });
        return this.list;
    },
    showPrompt: function(a) {
        this.actions = new Ext.ActionSheet({
            items: [ {
                text: "Approve friendship",
                ui: "confirm",
                scope: this,
                handler: function() {
                    Ext.dispatch({
                        controller: "friend",
                        action: "approveAction",
                        username: a
                    });
                    this.actions.hide(false);
                    this.actions.destroy();
                    delete this.actions;
                }
            }, {
                text: "Deny friendship",
                ui: "decline",
                scope: this,
                handler: function() {
                    Ext.dispatch({
                        controller: "friend",
                        action: "denyAction",
                        username: a
                    });
                    this.actions.hide(false);
                    this.actions.destroy();
                    delete this.actions;
                }
            }, {
                text: "Cancel",
                scope: this,
                handler: function() {
                    this.actions.hide(false);
                    this.actions.destroy();
                    delete this.actions;
                }
            } ]
        });
        this.actions.show();
    }
});

Ext.reg("bandcast.views.FriendRequests", bandcast.views.FriendRequests);

bandcast.views.FriendSearch = Ext.extend(Ext.form.FormPanel, {
    id: "friendsearch",
    initComponent: function() {
        this.toolbar = new Ext.Toolbar({
            title: "user search",
            items: [ {
                ui: "back",
                text: "Back",
                scope: this,
                handler: function() {
                    this.ownerCt.setActiveItem(this.prevCard, {
                        type: "slide",
                        reverse: true,
                        scope: this,
                        after: function() {
                            this.destroy();
                        }
                    });
                }
            } ]
        });
        Ext.apply(this, {
            scroll: "vertical",
            defaults: {
                xtype: "fieldset",
                defaults: {
                    labelWidth: "35%"
                }
            },
            listeners: {
                beforesubmit: function(b, a) {
                    Ext.dispatch({
                        controller: "friend",
                        action: "searchAction",
                        form: b,
                        values: a
                    });
                    return false;
                }
            },
            items: [ {
                items: [ {
                    xtype: "textfield",
                    name: "username",
                    label: "Username",
                    autoCapitalize: false,
                    useClearIcon: true
                } ]
            }, {
                xtype: "button",
                text: "Search",
                scope: this,
                formBind: true,
                handler: function(a) {
                    this.submit();
                }
            } ],
            dockedItems: [ this.toolbar ]
        });
        bandcast.views.FriendSearch.superclass.initComponent.call(this);
    }
});

Ext.reg("bandcast.views.FriendSearch", bandcast.views.FriendSearch);

bandcast.views.VenueList = Ext.extend(Ext.Panel, {
    id: "venuelist",
    layout: "card",
    historyUrl: "venue/list",
    initComponent: function() {
        this.wrapper = new Ext.Panel({
            layout: "fit",
            items: this.buildList(),
            dockedItems: [ {
                xtype: "toolbar",
                title: "the venues"
            } ]
        });
        Ext.apply(this, {
            items: [ this.wrapper ]
        });
        bandcast.views.VenueList.superclass.initComponent.call(this);
    },
    buildList: function() {
        this.list = new Ext.List({
            store: bandcast.stores.Venue,
            loadingText: "Loading",
            itemTpl: new Ext.XTemplate('<tpl for=".">', '<div class="primary">{name}</div>', "</tpl>"),
            listeners: {
                itemtap: {
                    fn: function(a, b, f, d) {
                        var c = a.getSelectionModel();
                        c.select(b);
                        (new Ext.util.DelayedTask(function() {
                            a.getSelectionModel().deselectAll();
                        }, this)).delay(400);
                        this.showVenue(a.getSelectedRecords()[0].data.urlkey);
                    },
                    scope: this
                },
                afterrender: {
                    fn: function(a) {
                        if (!this.list.store.getCount()) {
                            a.setLoading(true);
                            a.store.load();
                        }
                    },
                    scope: this
                }
            }
        });
        return this.list;
    },
    showVenue: function(a) {
        Ext.dispatch({
            controller: "venue",
            action: "detail",
            historyUrl: "venue/-/" + a,
            prevCard: this.wrapper,
            prevUrl: this.historyUrl,
            venue: a,
            parent: this
        });
    }
});

Ext.reg("bandcast.views.VenueList", bandcast.views.VenueList);

bandcast.views.VenueCheckin = Ext.extend(Ext.Sheet, {
    id: "venuecheckin",
    hideOnMaskTap: true,
    checked: null,
    scroll: "vertical",
    stretchX: true,
    stretchY: true,
    initComponent: function() {
        Ext.apply(this, {
            items: {
                xtype: "fieldset",
                cls: "radio-checkin",
                defaults: {
                    xtype: "radiofield",
                    labelWidth: "100%",
                    listeners: {
                        render: function(a) {
                            if (a.labelEl) {
                                a.labelEl.on("click", function() {
                                    a.setChecked(true);
                                }, a);
                            }
                        },
                        check: {
                            fn: function(a) {
                                this.checked = a;
                            },
                            scope: this
                        }
                    }
                },
                items: this.getVenues()
            },
            dockedItems: {
                xtype: "button",
                text: "Check in",
                ui: "action",
                dock: "bottom",
                scope: this,
                handler: function(a, b) {
                    Ext.dispatch({
                        controller: "venue",
                        action: "checkinAction",
                        id: this.checked.value,
                        name: this.checked.label
                    });
                    a.up().destroy();
                    return false;
                }
            },
            listeners: {
                hide: function(a) {
                    if (typeof this.callback == "function") {
                        a.destroy();
                        this.callback();
                    }
                }
            }
        });
        bandcast.views.VenueCheckin.superclass.initComponent.apply(this, arguments);
    },
    getVenues: function() {
        var a = Ext.getStore("venue"), b = [];
        if (a) {
            a.sort("name", "ASC");
            a.each(function(c) {
                b.push({
                    name: "venue",
                    label: c.get("name"),
                    value: c.get("id")
                });
            });
        }
        return b;
    },
    alignTo: function(a, c, b) {
        b -= 10;
        bandcast.views.VenueCheckin.superclass.alignTo.apply(this, [ a, c, b ]);
    }
});

Ext.reg("bandcast.views.VenueCheckin", bandcast.views.VenueCheckin);

bandcast.views.VenueDetail = Ext.extend(Ext.Panel, {
    id: "venuedetail",
    layout: "card",
    initComponent: function() {
        var a = Ext.getCmp(this.id);
        if (a) {
            if (a.prevCard) {
                a.ownerCt.setActiveItem(a.prevCard);
            }
            a.destroy();
        }
        this.toolbar = new Ext.Toolbar({
            items: !this.prevCard ? [] : [ {
                ui: "back",
                text: "Back",
                scope: this,
                handler: function() {
                    Ext.History.add(this.prevUrl);
                    this.ownerCt.setActiveItem(this.prevCard, {
                        type: "slide",
                        reverse: true,
                        scope: this,
                        after: function() {
                            this.destroy();
                        }
                    });
                }
            } ]
        });
        if (this.venue) {
            this.toolbar.setTitle(this.venue.get("name").toLowerCase());
        }
        this.wrapper = new Ext.Panel({
            layout: "fit",
            items: this.buildList(),
            dockedItems: this.toolbar
        });
        Ext.apply(this, {
            items: [ this.wrapper ]
        });
        bandcast.views.VenueDetail.superclass.initComponent.call(this);
    },
    buildList: function() {
        this.list = new Ext.List({
            store: bandcast.stores.Event,
            grouped: true,
            indexBar: Ext.is.Phone,
            loadingText: "Loading",
            itemTpl: new Ext.XTemplate('<tpl for=".">', '<div class="primary">{name}</div>', '<div class="secondary">{started:this.date} to {ended:this.date}</div>', "</tpl>", {
                date: function(a) {
                    var b = bandcast.timezoned(a);
                    return b.format(bandcast.config.event.date.format.timeshort);
                },
                compiled: true
            }),
            listeners: {
                afterrender: {
                    fn: function(a) {
                        if (!this.list.store.getCount()) {
                            a.setLoading(true);
                            a.store.load({
                                scope: this,
                                callback: function(c, b, d) {
                                    this.filterStore(a.store);
                                }
                            });
                        } else {
                            this.filterStore(a.store);
                        }
                    },
                    scope: this
                }
            }
        });
        return this.list;
    },
    filterStore: function(a) {
        a.clearFilter();
        a.filter("venue", this.venue.get("name"));
        a.sortTime();
    }
});

Ext.reg("bandcast.views.VenueDetail", bandcast.views.VenueDetail);

bandcast.views.ScheduleList = Ext.extend(Ext.Panel, {
    id: "schedulelist",
    layout: "card",
    historyUrl: "schedule/list",
    initComponent: function() {
        this.wrapper = new Ext.Panel({
            layout: "fit",
            items: this.buildList(),
            dockedItems: [ {
                xtype: "toolbar",
                title: "schedule"
            } ]
        });
        Ext.apply(this, {
            items: [ this.wrapper ]
        });
        bandcast.views.ScheduleList.superclass.initComponent.call(this);
    },
    buildList: function() {
        this.list = new Ext.List({
            store: bandcast.stores.Schedule,
            loadingText: "Loading",
            grouped: true,
            plugins: [ {
                ptype: "pullrefresh",
                pullRefreshText: "Pull down to refresh",
                releaseRefreshText: "Release to refresh",
                loadingText: "Loading..."
            } ],
            itemTpl: new Ext.XTemplate('<tpl for=".">', '<div class="primary{users:this.mine}">', "{name}<br />", '<span class="tertiary">{users:this.users}</span>', "</div>", "</tpl>", {
                users: function(d) {
                    if (d) {
                        var b, e = [];
                        for (var c = 0, a = d.length; c < a; c++) {
                            if (b = bandcast.stores.Friend.getById(d[c].id)) {
                                e.push(b.get("displayname") + (d[c].attending != 2 ? " (Maybe)" : ""));
                            } else {
                                if (d[c].id == Ext.data.auth.get("user").id) {
                                    e.push("Me" + (d[c].attending != 2 ? " (Maybe)" : ""));
                                }
                            }
                        }
                        return e.join(", ");
                    }
                },
                mine: function(c) {
                    if (c) {
                        for (var b = 0, a = c.length; b < a; b++) {
                            if (c[b].id == Ext.data.auth.get("user").id) {
                                return " self";
                            }
                        }
                    }
                }
            }),
            listeners: {
                afterrender: {
                    fn: function(a) {
                        a.setLoading(true);
                        if (!bandcast.stores.Friend.getCount()) {
                            bandcast.stores.Friend.load({
                                scope: this,
                                callback: function(c, b, d) {
                                    if (d) {
                                        a.store.load();
                                    }
                                }
                            });
                        } else {
                            a.store.load();
                        }
                    },
                    scope: this
                }
            }
        });
        return this.list;
    }
});

Ext.reg("bandcast.views.ScheduleList", bandcast.views.ScheduleList);

bandcast.views.MoreIndex = Ext.extend(Ext.Panel, {
    id: "moreindex",
    layout: "card",
    initComponent: function() {
        this.list = new Ext.Panel({
            scroll: "vertical",
            items: [ new Ext.Panel({
                items: {
                    styleHtmlContent: true,
                    tpl: new Ext.Template([ '<div class="section centered">', '<div><img src="https://chart.googleapis.com/chart?chs={width}x{height}&cht=qr&chl={url}&choe=UTF-8&chld=L|3" id="qrcode" width="{width}" height="{height}" alt="{username}" /></div>', '<div class="blurb">', "Have your friends scan this using a barcode scanner (such as RedLaser or NeoReader) and you'll be able to see each other's checkins.", '<div class="tip">', "<strong>Tip</strong> Save this to your photo album for quick access.", "</div>", "</div>", "</div>" ]),
                    data: {
                        width: 200,
                        height: 200,
                        url: encodeURIComponent(bandcast.config.defaults.urls.mobile + "/#qr/friend/" + Ext.data.auth.get("user").username + "/" + Ext.data.auth.get("user").qrcode),
                        username: Ext.data.auth.get("user").username
                    }
                },
                dockedItems: {
                    xtype: "toolbar",
                    title: "connect with friends instantly",
                    ui: "light",
                    cls: "small_title"
                }
            }), new Ext.Panel({
                items: {
                    styleHtmlContent: true,
                    tpl: new Ext.Template([ '<div class="section centered">', '<div class="blurb">', "If you're having trouble checking in because the network is overwhelmed you can check in via phone. Just call {phone} and follow the instructions.", "</div>", "</div>" ]),
                    data: {
                        phone: '<a href="tel:' + bandcast.config.event.twilio.phone.replace(/[^0-9]/g, "") + '">' + bandcast.config.event.twilio.phone + "</a>"
                    }
                },
                dockedItems: {
                    xtype: "toolbar",
                    title: "having trouble checking in",
                    ui: "light",
                    cls: "small_title"
                }
            }), new Ext.Panel({
                items: {
                    styleHtmlContent: true,
                    html: [ '<div class="section centered">', '<div class="blurb">', 'Bandcast was developed by <a href="http://phorklabs.com" rel="external">Phork Labs</a>.', "</div>", "</div>" ].join("")
                },
                dockedItems: {
                    xtype: "toolbar",
                    title: "about bandcast",
                    ui: "light",
                    cls: "small_title"
                }
            }) ],
            dockedItems: [ {
                xtype: "toolbar",
                title: "bandcast",
                items: [ {
                    ui: "button",
                    iconCls: "settings",
                    iconMask: true,
                    scope: this,
                    handler: function(a, b) {
                        Ext.dispatch({
                            controller: "more",
                            action: "settings",
                            historyUrl: "more/settings",
                            prevCard: this.list,
                            parent: this
                        });
                    }
                }, {
                    xtype: "spacer",
                    flex: 1
                }, {
                    ui: "button",
                    text: "Logout",
                    scope: this,
                    handler: function(a, b) {
                        this.destroy();
                        Ext.dispatch({
                            controller: "auth",
                            action: "logout"
                        });
                    }
                } ]
            } ]
        });
        Ext.apply(this, {
            items: [ this.list ]
        });
        bandcast.views.MoreIndex.superclass.initComponent.call(this);
    }
});

Ext.reg("bandcast.views.MoreIndex", bandcast.views.MoreIndex);

bandcast.views.MoreSettings = Ext.extend(Ext.form.FormPanel, {
    id: "moresettings",
    initComponent: function() {
        this.toolbar = new Ext.Toolbar({
            title: "settings",
            items: [ {
                ui: "back",
                text: "Back",
                scope: this,
                handler: function() {
                    this.ownerCt.setActiveItem(this.prevCard, {
                        type: "slide",
                        reverse: true,
                        scope: this,
                        after: function() {
                            this.destroy();
                        }
                    });
                }
            } ]
        });
        Ext.apply(this, {
            scroll: "vertical",
            defaults: {
                xtype: "fieldset",
                defaults: {
                    labelWidth: "35%"
                }
            },
            listeners: {
                beforesubmit: function(b, a) {
                    Ext.dispatch({
                        controller: "more",
                        action: "settingsAction",
                        form: b,
                        values: a
                    });
                    return false;
                }
            },
            items: [ {
                instructions: "Optional account settings. Leave the password field blank to keep your existing password.",
                items: [ {
                    xtype: "textfield",
                    name: "displayname",
                    label: "Name",
                    value: Ext.data.auth.get("user").displayname,
                    placeHolder: Ext.data.auth.get("user").username,
                    autoCapitalize: false,
                    useClearIcon: true
                }, {
                    xtype: "textfield",
                    name: "email",
                    label: "Email",
                    value: Ext.data.auth.get("user").email,
                    autoCapitalize: false,
                    useClearIcon: true
                }, {
                    xtype: "passwordfield",
                    name: "password",
                    label: "Password",
                    useClearIcon: true
                } ]
            }, {
                instructions: "Enter your US phone number and choose a pin number to check in by telephone.",
                items: [ {
                    xtype: "textfield",
                    name: "phone",
                    label: "Phone",
                    value: Ext.data.auth.get("user").phone,
                    placeHolder: bandcast.config.event.twilio.phone,
                    autoCapitalize: false,
                    useClearIcon: true
                }, {
                    xtype: "textfield",
                    name: "pin",
                    label: "Pin #",
                    value: Ext.data.auth.get("user").pin,
                    placeHolder: Ext.data.auth.get("user").pin || "1234",
                    autoCapitalize: false,
                    useClearIcon: true
                } ]
            }, {
                instructions: "Please enter your current password to make changes.",
                items: [ {
                    xtype: "passwordfield",
                    name: "verify",
                    label: "Password",
                    useClearIcon: true
                } ]
            }, {
                xtype: "button",
                text: "Save settings",
                scope: this,
                formBind: true,
                handler: function(a) {
                    this.submit();
                }
            } ],
            dockedItems: [ this.toolbar ]
        });
        bandcast.views.MoreSettings.superclass.initComponent.call(this);
    }
});

Ext.reg("bandcast.views.MoreSettings", bandcast.views.MoreSettings);

bandcast.views.MusicFest = Ext.extend(Ext.Panel, {
    initComponent: function() {
        if (typeof this.active == "string") {
            var b = this.active.split("/")[0], c = {
                activity: 0,
                user: 1,
                friend: 1,
                event: 2,
                schedule: 3,
                more: 4
            }, d = 0;
            if (typeof c[b] == "number") {
                d = c[b];
            }
        }
        var a = new Ext.TabPanel({
            id: "viewport",
            cardSwitchAnimation: "fade",
            fullscreen: true,
            layout: "hbox",
            activeItem: d,
            listeners: {
                cardswitch: function(g, h, f, e) {
                    Ext.History.add(h.historyUrl);
                }
            },
            tabBar: {
                ui: "gray",
                dock: "bottom",
                layout: {
                    pack: "center"
                }
            },
            items: [ {
                xtype: "bandcast.views.ActivityList",
                title: "Activity",
                iconCls: "chat3",
                historyUrl: "activity/list"
            }, {
                xtype: "bandcast.views.FriendList",
                title: "Friends",
                iconCls: "team1",
                historyUrl: "friend/list"
            }, {
                xtype: "bandcast.views.EventList",
                title: "Bands",
                iconCls: "music1",
                historyUrl: "event/list"
            }, {
                xtype: "bandcast.views.ScheduleList",
                title: "Schedule",
                iconCls: "calendar2",
                historyUrl: "schedule/list"
            }, {
                xtype: "bandcast.views.MoreIndex",
                title: "More",
                iconCls: "more",
                historyUrl: "more/index"
            } ]
        });
        Ext.apply(this, {
            items: a
        });
        bandcast.views.MusicFest.superclass.initComponent.call(this);
    }
});

Ext.reg("bandcast.views.MusicFest", bandcast.views.MusicFest);

Ext.regController("auth", {
    index: function(a) {
        this.callback = a.callback;
        this.login(a);
    },
    login: function(a) {
        this.render({
            xtype: "bandcast.views.Login"
        });
    },
    loginAction: function(a) {
        var b = new Ext.LoadMask("loginform", {
            msg: "Logging in"
        });
        b.show();
        Ext.data.auth.login(a.values.username, a.values.password, Ext.createDelegate(function(c, d) {
            b.hide();
            delete b;
            if (c) {
                a.form.destroy();
                this.callback();
            } else {
                Ext.Msg.alert("Log in error", (d ? d : "Something went wrong.") + ". Please try again.", Ext.emptyFn);
            }
        }, this));
    },
    register: function(a) {
        this.render({
            xtype: "bandcast.views.Register"
        });
    },
    registerAction: function(a) {
        var b = new Ext.LoadMask("registerform", {
            msg: "Registering"
        });
        b.show();
        Ext.data.auth.register(a.values.username, a.values.password, a.values.email, Ext.createDelegate(function(c, d) {
            b.hide();
            delete b;
            if (c) {
                a.form.destroy();
                this.callback();
            } else {
                Ext.Msg.alert("Register error", (d ? d : "There was an error creating your account") + ". Please try again.", Ext.emptyFn);
            }
        }, this));
    },
    password: function(a) {
        this.render({
            xtype: "bandcast.views.Password"
        });
    },
    passwordAction: function(a) {
        var b = new Ext.LoadMask("passwordform", {
            msg: "Loading"
        });
        b.show();
        Ext.data.auth.password(a.values.email, Ext.createDelegate(function(c, d) {
            b.hide();
            delete b;
            if (c) {
                a.form.destroy();
                this.login(a);
                Ext.Msg.alert("Check your email", "An email has been sent with instructions to reset your password.");
            } else {
                Ext.Msg.alert("Password error", (d ? d : "There was an error resetting your password") + ". Please try again.", Ext.emptyFn);
            }
        }, this));
    },
    logout: function(a) {
        Ext.data.auth.destroy();
        Ext.redirect(bandcast.defaultUrl);
    }
});

Ext.regController("activity", {
    list: function(a) {
        this.activityList = this.render({
            xtype: "bandcast.views.ActivityList"
        });
    },
    add: function(a) {
        this.activityAdd = this.render({
            xtype: "bandcast.views.ActivityAdd",
            prevCard: a.prevCard,
            recipient: a.recipient
        });
        if (a.parent) {
            a.parent.setActiveItem(this.activityAdd, "slide");
        } else {
            this.activityAdd.show();
        }
    },
    addAction: function(b) {
        var c = Ext.ModelMgr.create({
            status: b.values.status,
            metadata: {
                recipient: b.values.recipient
            },
            created: new Date
        }, "Activity");
        var a = Ext.util.BandcastFlash.add("Posting your message ...");
        c.save({
            callback: function(d, e) {
                Ext.util.BandcastFlash.remove(a);
                if (e.success === true) {
                    Ext.util.BandcastFlash.add("Your message was posted!", {
                        timer: 800
                    });
                    Ext.getCmp("activitylist").list.getStore().load();
                } else {
                    Ext.util.BandcastFlash.error("Unable to save your message.");
                }
            }
        });
    }
});

Ext.regController("friend", {
    list: function(a) {
        this.friendList = this.render({
            xtype: "bandcast.views.FriendList"
        });
    },
    requests: function(a) {
        this.friendRequests = this.render({
            xtype: "bandcast.views.FriendRequests",
            prevCard: a.prevCard
        });
        if (a.parent) {
            a.parent.setActiveItem(this.friendRequests, "slide");
        } else {
            this.friendRequests.show();
        }
    },
    search: function(a) {
        this.friendSearch = this.render({
            xtype: "bandcast.views.FriendSearch",
            prevCard: a.prevCard
        });
        if (a.parent) {
            a.parent.setActiveItem(this.friendSearch, "slide");
        } else {
            this.friendSearch.show();
        }
    },
    searchAction: function(a) {
        var b = a.values.username;
        Ext.dispatch({
            controller: "user",
            action: "detail",
            historyUrl: "user/-/" + b,
            username: b
        });
    },
    addAction: function(b) {
        var a = Ext.util.BandcastFlash.add("Requesting friendship ...");
        bandcast.stores.Friend.addByUsername(b.username, function(c, d) {
            Ext.util.BandcastFlash.remove(a);
            if (c) {
                Ext.util.BandcastFlash.add("Your friendship request was sent!", {
                    timer: 800
                });
            } else {
                Ext.util.BandcastFlash.error("Unable to send your friendship request.");
            }
        });
    },
    approveAction: function(b) {
        var a = Ext.util.BandcastFlash.add("Approving friendship ...");
        bandcast.stores.Friend.approveByUsername(b.username, function(c, d) {
            Ext.util.BandcastFlash.remove(a);
            if (c) {
                Ext.util.BandcastFlash.add("Friendship approved!", {
                    timer: 800
                });
            } else {
                Ext.util.BandcastFlash.error("Unable to approve friendship.");
            }
        });
    },
    denyAction: function(b) {
        var a = Ext.util.BandcastFlash.add("Denying friendship ...");
        bandcast.stores.Friend.denyByUsername(b.username, function(c, d) {
            Ext.util.BandcastFlash.remove(a);
            if (c) {
                Ext.util.BandcastFlash.add("Friendship denied!", {
                    timer: 800
                });
            } else {
                Ext.util.BandcastFlash.error("Unable to deny friendship.");
            }
        });
    }
});

Ext.regController("user", {
    detail: function(d) {
        var b = bandcast.stores.Friend.findRecord("username", d.username), a = d.username == Ext.data.auth.get("user").username, e = b ? true : null, c = !!b, f = "slide";
        if (!b) {
            if (bandcast.stores.Friend.loaded) {
                e = false;
            }
            if (b = bandcast.stores.User.findRecord("username", d.username)) {
                c = true;
                e = b.get("relationship").friend == "approved";
            } else {
                b = Ext.ModelMgr.create({
                    username: d.username,
                    displayname: d.username
                }, "User");
            }
        }
        if (!d.parent) {
            if (d.parent = Ext.getCmp("friendlist")) {
                d.prevCard = d.parent.wrapper;
                d.prevUrl = d.parent.historyUrl;
            }
            f = null;
        }
        this.userDetail = this.render({
            xtype: "bandcast.views.UserDetail",
            prevCard: d.prevCard,
            prevUrl: d.prevUrl,
            user: b,
            loaded: c,
            friend: e
        });
        if (d.parent) {
            d.parent.setActiveItem(this.userDetail, f);
        } else {
            this.userDetail.show();
        }
        this.detailLoad(b, e || a, c);
    },
    detailLoad: function(a, c, b) {
        if (!b) {
            bandcast.stores.User.loadByUsername(a.get("username"), Ext.createDelegate(function(d) {
                if (typeof d[0] == "object") {
                    a = d[0];
                    c = c || a.get("relationship").friend == "approved";
                    Ext.getCmp("userinfo").update(Ext.apply(a.data, {
                        friend: c,
                        loaded: true,
                        self: a.get("username") == Ext.data.auth.get("user").username
                    }));
                    this.userDetail.user = a;
                    this.detailLoad(a, c, true);
                } else {
                    this.userDetail.invalidUser();
                }
            }, this));
        }
        if (a.get("id") && c !== false) {
            this.userDetail.allowMessage();
            this.userDetail.buildList();
        }
        if (a.get("id") && c === false) {
            this.userDetail.allowFriend();
        }
    }
});

Ext.regController("event", {
    list: function(a) {
        this.eventList = this.render({
            xtype: "bandcast.views.EventList"
        });
    },
    detail: function(a) {
        var b = bandcast.stores.Event.findRecord("urlkey", a.event), c = "slide";
        if (!a.parent) {
            if (a.parent = Ext.getCmp("eventlist")) {
                a.prevCard = a.parent.wrapper;
                a.prevUrl = a.parent.historyUrl;
                c = null;
            }
        }
        this.eventDetail = this.render({
            xtype: "bandcast.views.EventDetail",
            prevCard: a.prevCard,
            prevUrl: a.prevUrl,
            event: b
        });
        this.detailLoad(b);
        if (a.parent) {
            a.parent.setActiveItem(this.eventDetail, c);
        } else {
            this.eventDetail.show();
        }
    },
    detailLoad: function(f) {
        var b = f.get("artists"), e = [];
        if (b) {
            for (var d = 0, a = b.length; d < a; d++) {
                if (!bandcast.stores.Artist.getById(b[d].id)) {
                    e.push(b[d].id);
                }
            }
            if (e.length) {
                var c = new Ext.data.Operation({
                    action: "read",
                    filters: [ new Ext.util.Filter({
                        property: "id",
                        value: e
                    }) ]
                });
                bandcast.stores.Artist.getProxy().read(c, function(j) {
                    var h = c.getRecords();
                    bandcast.stores.Artist.loadRecords(h, true);
                    for (var k = 0, g = h.length; k < g; k++) {
                        var l = Ext.getDom("artist-" + h[k].get("id"));
                        if (l) {
                            Ext.DomHelper.overwrite(l, h[k].get("description") || "No information provided");
                        }
                    }
                    Ext.getCmp("eventdetail").doComponentLayout();
                }, this);
            }
        }
    },
    checkin: function(a) {
        this.eventCheckin = this.render({
            xtype: "bandcast.views.EventCheckin",
            callback: a.callback
        });
        this.eventCheckin.showBy(a.btn.up(), "fade", false, false);
    },
    checkinAction: function(b) {
        var c = Ext.ModelMgr.create({
            type: "event",
            typeid: b.id,
            checkin: (new Date).format("c")
        }, "Checkin");
        var a = Ext.util.BandcastFlash.add("Checking in to " + b.name + " ...");
        c.save({
            callback: function(d, e) {
                Ext.util.BandcastFlash.remove(a);
                if (e.success === true) {
                    Ext.util.BandcastFlash.add("You are checked in!", {
                        timer: 800
                    });
                    Ext.getCmp("activitylist").list.getStore().load();
                } else {
                    Ext.util.BandcastFlash.error("Unable to save your checkin.");
                }
            }
        });
    },
    rsvpAction: function(b) {
        var c = Ext.ModelMgr.create({
            type: "event",
            typeid: b.eventid,
            attending: b.value
        }, "Checkin");
        var a = Ext.util.BandcastFlash.add("Sending your response ...");
        c.save({
            callback: function(d, e) {
                Ext.util.BandcastFlash.remove(a);
                if (e.success === true) {
                    Ext.util.BandcastFlash.add("Your response was sent!", {
                        timer: 800
                    });
                    Ext.getCmp("activitylist").list.getStore().load();
                } else {
                    Ext.util.BandcastFlash.error("Unable to save your activity.");
                }
            }
        });
    }
});

Ext.regController("venue", {
    list: function(a) {
        this.venueList = this.render({
            xtype: "bandcast.views.VenueList"
        });
    },
    detail: function(a) {
        var c = bandcast.stores.Venue.findRecord("urlkey", a.venue), b = "slide";
        if (!a.parent) {
            if (a.parent = Ext.getCmp("activitylist")) {
                a.prevCard = a.parent.wrapper;
                a.prevUrl = a.parent.historyUrl;
                b = null;
            }
        }
        this.venueDetail = this.render({
            xtype: "bandcast.views.VenueDetail",
            prevCard: a.prevCard,
            prevUrl: a.prevUrl,
            venue: c
        });
        if (a.parent) {
            a.parent.setActiveItem(this.venueDetail, b);
        } else {
            this.venueDetail.show();
        }
    },
    checkin: function(a) {
        this.venueCheckin = this.render({
            xtype: "bandcast.views.VenueCheckin",
            callback: a.callback
        });
        this.venueCheckin.showBy(a.btn.up(), "fade", false, false);
    },
    checkinAction: function(b) {
        var c = Ext.ModelMgr.create({
            type: "venue",
            typeid: b.id,
            checkin: (new Date).format("c")
        }, "Checkin");
        var a = Ext.util.BandcastFlash.add("Checking in to " + b.name + " ...");
        c.save({
            callback: function(d, e) {
                Ext.util.BandcastFlash.remove(a);
                if (e.success === true) {
                    Ext.util.BandcastFlash.add("You have been checked in!", {
                        timer: 800
                    });
                    Ext.getCmp("activitylist").list.getStore().load();
                } else {
                    Ext.util.BandcastFlash.error("Unable to save your checkin.");
                }
            }
        });
    }
});

Ext.regController("schedule", {
    list: function(a) {
        this.scheduleList = this.render({
            xtype: "bandcast.views.ScheduleList"
        });
    }
});

Ext.regController("more", {
    index: function(a) {
        this.moreIndex = this.render({
            xtype: "bandcast.views.MoreIndex"
        });
    },
    settings: function(a) {
        this.moreSettings = this.render({
            xtype: "bandcast.views.MoreSettings",
            prevCard: a.prevCard
        });
        if (a.parent) {
            a.parent.setActiveItem(this.moreSettings, "slide");
        } else {
            this.moreSettings.show();
        }
    },
    settingsAction: function(b) {
        var a = Ext.util.BandcastFlash.add("Saving settings ...");
        Ext.data.auth.settings(b.values, Ext.createDelegate(function(c, d) {
            Ext.util.BandcastFlash.remove(a);
            if (c) {
                Ext.util.BandcastFlash.add("Your settings were saved!", {
                    timer: 800
                });
            } else {
                Ext.util.BandcastFlash.error("Unable to save your settings.", d);
            }
        }, this));
    }
});

Ext.regController("qrcode", {
    friend: function(b) {
        if (b.username && b.qrcode) {
            var a = Ext.util.BandcastFlash.add("Adding connection ...");
            bandcast.stores.Friend.addByQr(b.username, b.qrcode, function(c, d) {
                Ext.util.BandcastFlash.remove(a);
                if (c) {
                    Ext.util.BandcastFlash.add("You are now connected!", {
                        timer: 800
                    });
                } else {
                    Ext.util.BandcastFlash.error("Connection error.");
                }
            });
        } else {
            Ext.util.BandcastFlash.error("Incomplete friend data.");
        }
    }
});

Ext.regController("musicfest", {
    run: function(a) {
        Ext.applyIf(bandcast.config, {
            aliases: {
                event: {
                    single: "band",
                    plural: "bands"
                },
                venue: {
                    single: "stage",
                    plural: "stages"
                },
                meetup: {
                    single: "meetup",
                    plural: "meetups"
                }
            }
        });
        this.render({
            xtype: "bandcast.views.MusicFest",
            active: a.url
        });
        if (a.url) {
            Ext.redirect(a.url);
        } else {
            this.index();
        }
    },
    index: function(a) {
        Ext.dispatch({
            controller: "activity",
            action: "list",
            historyUrl: "activity/list",
            options: a
        });
    }
});