// TimeStamper namespace
var TS = {};

/* Setup after the document is ready for manipulation. */
$(document).ready(function(){

    // ======== DEFINE MODELS ========//

    /* Entry model.
     * Attributes
     *  - id
     *  - mark
     *  - notes
     *  - start
     */
    TS.EntryModel = Backbone.Model.extend({

    });

    /* Timeline model.
     * Attributes:
     *  - id
     *  - desc
     *  - created
     */
    TS.TimelineModel = Backbone.Model.extend({

    });

    /* User model.
     * Attributes:
     *  - username
     *  - fullname
     *  - email
     *  - join_date
     */
    TS.UserModel = Backbone.Model.extend({
        url: function() { return '/ts_api/users/' + this.get('id'); },

        initialize: function(attrs, options) {
            _.bind(this, 'url');
        }
    });

    TS.EntryList = Backbone.Collection.extend({
        model: TS.EntryModel,
        
        comparator: function(entry) { return entry.get('timestamp'); },

        initialize: function(model, options) {
            if (options.timeline == undefined) {
                throw "Cannot create an EntryList without a TimelineModel reference."
            } else { this.timeline = options.timeline; }

            _.bindAll(this, "url");
        },

        url: function() {
            return "/entries/" + this.timeline.get('user_id') + "/" + this.timeline.get('id');
        }
    });

    TS.TimelineList = Backbone.Collection.extend({
        model: TS.TimelineModel,

        initialize: function(models, options) {
            if (options.user == undefined) {
                throw "Cannot create a TimelineList without a UserModel reference.";
            } else { this.user = options.user; }

            _.bindAll(this, 'url');
        },

        comparator: function(timeline) {
            return timeline.get('id');
        },

        url: function() {
            return "/ts_api/timelines/" + this.user.get('id');
        }
    });


    // ======== DEFINE VIEWS ========//

    /* Entry view
     */
    TS.EntryView = Backbone.View.extend({

        model: TS.EntryModel,

        events: {
            "dblclick div.mark"         : "editMark",
            "dblclick div.timestamp"    : "editTimestamp",
            "keypress .mark-input"      : "updateOnEnter",
            "keypress .timestamp-input" : "updateOnEnter"
        },

        initialize: function() {
            _.bindAll(this, 'render', 'close', 'editTImestamp',
                'editMark', 'updateOnEnter');
            this.model.bind('change', this.render);
            this.model.view = this;
        },

        render: function() {
            $(this.el).html(ich.entry(this.model.toJSON()));
            return this;
        },

        editMark: function() {
            $(this.el).addClass('edit-mark');
            this.$('.mark-input').focus();
            return this;
        },

        editTimestamp: function() {
            $(this.el).addClass('edit-timestamp');
            this.$('timestamp-input').focus();
            return this;
        },

        close: function() {
            this.model.save({
                mark: this.$('.mark-input').val(), 
                timestamp: this.$('.timestamp-input').val()});
            $(this.el).removeClass('edit-mark edit-timestamp');
        },

        updateOnEnter: function(e) {
            if(e.keyCode == 13) this.close();
        }
    });

    TS.EntryListView = Backbone.View.extend({
        
        el: $("#entry-list"),

        events: {
            "#new-entry"    : "createNewEntry"
        },

        initialize: function() {
            _.bindAll(this, 'addOne', 'createNewEntry', 'render');
            this.collection.bind('add', this.addOne);
            this.collection.bind('refresh', this.render);
            this.collection.view = this;
            this.entryContainer = this.$("#entries")
        },

        addOne: function(entry) {
            if (!entry.view) { new TS.EntryView({model: entry}); }
            this.entryContainer.prepend(entry.view.render().el);
        },

        createNewEntry: function() {
            var entryMark = this.$("#new-entry-input").val();
            var newEntry = TS.EntryModel({mark: entryMark});
            this.collection.create({mark: entryMark}).fetch();
        },

        render: function() {
            this.entryContainer.empty();
            this.collection.each(this.addOne);
        }
    });

    TS.TimelineView = Backbone.View.extend({

        el: $("#timeline"),

        model: TS.TimelineModel,

        events: {
            "dblclick .timeline-id"         : "editId",
            "dblclick .timeline-desc"       : "editDesc",
            "keypress .timeline-id-input"   : "updateOnEnter",
            "keypress .timeline-desc-input" : "updateOnEnter"
        },

        initialize: function() {
            _.bindAll(this, 'render', 'close', 'editId', 'editDesc',
                'updateOnEnter');
            this.model.bind('change', this.render);
            this.model.view = this;
        },

        render: function() {
            this.$('.timeline-id').html('( ' +
                this.model.get('id') + ' )');
            this.$('.timeline-desc').text(this.model.get('desc'));
            return this;
        },

        editId: function() {
            $(this.el).addClass('edit-id');
            this.$('.timeline-id-input').focus();
            return this;
        },

        editDesc: function() {
            $(this.el).addClass('edit-desc');
            this.$('.timeline-desc-input').focus();
            return this;
        },

        close: function() {
            this.model.save({
                id: this.$('timeline-id-input').val(),
                desc: this.$('.timeline-desc-input').val()});
            $(this.el).removeClass('.edit-id .edit-desc');
        },

        updateOnEnter: function(e) {
            if (e.keyCode == 13) this.close();
        }
    });

    TS.TimelineListView = Backbone.View.extend({
        el: $("#timeline .drop-menu-items"),

        collection: TS.TimelineList,

        initialize: function() {
            _.bindAll(this, 'render', 'renderOne');
            this.collection.bind('add', this.renderOne);
            this.collection.bind('refresh', this.render);
            this.collection.view = this;
        },

        renderOne: function(timeline) {
            if (!timeline.view) { new TS.TimelineView(timeline); }
            $(this.el).append(ich.timelineLink(timeline.toJSON()));
        },

        render: function() {
            $(this.el).remove(".timeline-link");
            this.collection.each(this.renderOne);
            return this;
        }
    });

    TS.UserView = Backbone.View.extend({
        
        el: $("#user"),

        model: TS.UserModel,

        events: {
            'dblclick .fullname':       'editFullname',
            'keypress .fullname-input': 'updateOnEnter'
        },

        initialize: function() {
            _.bindAll(this, 'render', 'close', 'editFullname', 'updateOnEnter');
            this.model.bind('change', this.render);
            this.model.view = this;
        },

        render: function() {
            this.$('.fullname').text(this.model.get('name'));
            this.$('.username').text(" - " + this.model.get('id'));
            return this;
        },

        editFullname: function() {
            $(this.el).addClass('.edit-fullname');
            this.$('.fullname-input').focus();
            return this;
        },

        close: function() {
            this.model.set({name: this.$('.fullname-input').val()});
            this.model.save();
            $(this.el).removeClass('.edit-fullname');
        },

        updateOnEnter: function(e) {
            if (keyCode == 13) this.close();
        }
    });

    TS.AppView = Backbone.View.extend({

        el: $("body"),

        events: {
            'click #timeline .drop-menu-items a': 'selectTimeline',
            'keypress #new-entry-input'         : 'newTimestamp',
        },

        initialize: function() {
            _.bindAll(this, 'render');
        },

        renderTimelineList: function() {
            var tlUL = this.$('#timeline ul.drop-menu-items');
            //var curTimeline = 
            //var remTimelines = TS.user.timelines.filter(function(timeline)
        }
    });

    // wire the login dialog using jQuery UI
    $("#login-dialog").dialog({
        autoOpen: false,
        height: 400,
        width: 400,
        modal: true,
        buttons: { Login: function(){login()} }
    });

    $('#login-dialog').dialog('open');

})

function login() {
    // lookup the login dialog elements
    var name = $("#login-name");
    var pwd = $("#login-password");

    // call the API via AJAX
    $.ajax({
        url: "/ts_api/login",
        processData: false,
        data: JSON.stringify({username: name.val(), password: pwd.val()}),
        type: "POST",

        error: function(jqXHR, textStatus, error) {
            // assuming bad credentials (possible server error or bad request,
            // we should check that, FIXME
            var tips = $(".validate-tips");
            tips.text("Incorrect username/password combination.");
            tips.addClass("ui-state-error");
            tips.slideDown();
        },

        success: function(data, textStatus, jqXHR) {

            // initialize the app data 
            // TODO: possiblty replace by script generated server-side

            // create the user model
            TS.user = new TS.UserModel({
                id: name.val(),
                name: '' });

            // fetch the initial user data from the server
            TS.user.fetch();

            // create the user view
            new TS.UserView({model: TS.user});
            TS.user.view.render();

        }});
}