/// <reference path="http://localhost/IndustrialDashboard/Scripts/IndustrialDashboard.js" />

define([
  // Application.
  "app",

  //templates-loader
  "js/templates-loader",

  "Mousetrap",

  //"js/bootstrap-datepicker/js/bootstrap-datepicker",
  "js/bootstrap-timepicker/js/bootstrap-timepicker",
],

function (app, T, Mousetrap) {

    var DateTimeControl = { Model: {}, Views: {} }

    DateTimeControl.Model = Backbone.Model.extend({
        superClass: null,
        defaults: {
            date: '',
            time: '',
            datetime: '',
        },
        constructor: function (attrs)
        {
            //_.bindAll(this);

            this.superClass = DateTimeControl.Model.__super__;

            this.superClass.constructor.apply(this, arguments);

            this.set('datetime', new Date(), { silent: true, });

            this.set(attrs, { silent: true, });
        },
        //initialize: function () {
        //    _.bindAll(this);

        //    //this.listenTo(this, "change:datetime", this.update_startend); 

        //    //this.update_startend(); 
        //},
        //, update_startend: function () {
        //    this.set("start", this.get("datetime"));
        //    var startDate = Core.DateTime.Parse(this.get("start"));
        //    var endDate = new Date(startDate.getTime() + 1000 * parseInt(this.get("interval"), 10));
        //    this.set("end", Core.DateTime.ToString(endDate, "yyyy-mm-dd HH:MM:ss"));
        //    //logging
        //    //_.each(this.attributes, function (value, key) {
        //    //    console.log(key + ": " + value); 
        //    //}); 
        //}
        getTime: function () {
            //return Core.DateTime.ToString(Core.DateTime.Parse(this.get("datetime")), "HH:MM:ss");
            return this.get('time');
        },
        setTime: function (time) {
            //this.set("datetime", Core.DateTime.ToString(Core.DateTime.Parse(this.get("datetime")), "yyyy-mm-dd") + " " + time);
            this.set('time', time);
        },
        setDate: function (date) {
            //this.set("datetime", date + " " + Core.DateTime.ToString(Core.DateTime.Parse(this.get("datetime")), "HH:MM:ss"));
            this.set('date', date);
        },
        getDate: function () {
            //return Core.DateTime.ToString(Core.DateTime.Parse(this.get("datetime")), "yyyy-mm-dd");
            return this.get('date');
        },
        set: function (key, val, options) {
            if (key == null) return this;

            var attrs;

            // Handle both `'key', value` and `{key: value}` -style arguments.
            if (typeof key === 'object') {
                attrs = key;
                options = val;
            } else {
                (attrs = {})[key] = val;
            }

            if (!options)
                options = {};

            var dateCurrent = this.get('date'),
                dateNew = attrs.date,
                dateSet = (typeof attrs.date !== 'undefined'),
                timeCurrent = this.get('time'),
                timeNew = attrs.time,
                timeSet = (typeof attrs.time !== 'undefined'),
                datetimeNew = attrs.datetime,
                datetimeSet = (typeof attrs.datetime !== 'undefined'),
                datetimeCurrent = this.get('datetime');

            var dateChanging = ((dateSet == true) && (dateNew != dateCurrent)),
                timeChanging = ((timeSet == true) && (timeNew != timeCurrent)),
                datetimeChanging = ((datetimeSet == true) && (datetimeNew != datetimeCurrent));


            if (datetimeSet == true)
            {
                if (datetimeNew) {
                    var datetimeFixed = Core.DateTime.Parse(datetimeNew);

                    attrs.date = Core.DateTime.ToString(datetimeFixed, "yyyy-mm-dd");
                    attrs.time = Core.DateTime.ToString(datetimeFixed, "HH:MM:ss");
                }
                else {
                    attrs.date = '';
                    attrs.time = '';
                    attrs.datetime = '';
                }
            }
            else if ((dateChanging == true) || (timeChanging == true)) {
                var dateFixed = (dateChanging == true)
                                    ? (dateNew) 
                                        ? dateNew 
                                        : ''
                                    : dateCurrent,
                    timeFixed = (timeChanging == true)
                                    ? (timeNew) 
                                        ? timeNew 
                                        : ''
                                    : timeCurrent;
                

                attrs.datetime = $.trim(dateFixed + " " + timeFixed);
            }

            this.superClass.set.call(this, attrs, options);
        },
    });

    DateTimeControl.Views.Main = Backbone.View.extend({
        template: "dateTimeControl/dateTimeControl"
        , id: "global-datetime-control"
        , title: ""
        //default not cacheable, change this if you want the view to be cacheable
        // if the view is set as cacheable should also have a refresh method to reset the view without erasing the DOM.
        //refreshing only the data, maybe?
        , isCacheable: false
        , modelChanging: false

        , initialize: function () {
            this.options.MYREFERENCES = {
                timepicker: {
                    isFocused: false
                },
                autoupdate: {
                    enabled: ((_.isBoolean(this.options.autoupdate)) ? this.options.autoupdate : false),
                    toid: null, 
                }, 
            };

            _.bindAll(this); 

            this.model = (this.options.model) ? this.options.model : new DateTimeControl.Model();

            this.listenTo(this.model, "change:date", this.dateModelChanged);
            this.listenTo(this.model, "change:time", this.timeModelChanged);

            this.bindEvents();
        },
        // global view variable (seen in this scope, public to the view, and SHARED BETWEEN OTHER INSTANCES OF THE SAME VIEW)
        // containing all the variables for this view

        //properties that you wanna scope as private variables for each instance of a view should not be placed here
        //the only way i found to maintain the variables between instances of the same view, is either using models,
        // (each view will have its own model so data is not shared between them), or in case you don't want to use a model
        // you can use the Backbone.View.options object, and doing something like
        // this.options.attributes = {}
        // and storing every single variable inside attributes.

        events: {
            "click #datetime_calendar-icon-clickeable": "showCalendar"
            , "focus #datetime_datePicker": "showCalendarFocus"
            , "blur #datetime_datePicker": "calendarChanged"
            , "keydown #datetime_datePicker": "calendar_onKeyDown"
            //, "click #datetime_time-icon-clickeable": "dateIcon_click"
            , "focus #datetime_timePicker": "timepicker_focus"
            , "blur #datetime_timePicker": "timepicker_blur"
            , "keydown #datetime_timePicker": "timepicker_onKeyDown"
        },

        render: function (container, callback) {
            var that = this;
            var thatContainer = container;

            T.render.call(this, this.template, function (tmp) {
                //getInternationalizationData
                if (!that.options.i18n) that.options.i18n = {};
                app.getI18NJed(that, that.template, function (i18nJED) {
                    //storing internationalization data
                    that.options.i18n[that.template] = i18nJED;

                    //start: before the view is visible, but the template was already loaded (not instanced nor appended)

                    //end:

                    //loading the view and appeding it to the views's $el.
                    that.$el.html(tmp());

                    //start: the view was already loaded an is on a div element, but not appended to the main container
                    //here you can perform anything you want DOM related, by getting the dom element via that.$el.find("#id")

                    that.options.MYREFERENCES.datePicker = that.$el.find("#datetime_datePicker").datepicker(
                        _.extend({
                            showOn: "focus"
                            , beforeShow: function () { that.calendarBeforeShow.call(that); }
                            , onSelect: function () { that.calendarChanged.call(that); }
                            , showOtherMonths: true
                            , selectOtherMonths: true
                            , dateFormat: 'yy-mm-dd'
                        }, that.options.datepicker_options || {})
                    );

                    var d = that.model.getDate(); 
                    if (d != '') {
                        that.options.MYREFERENCES.datePicker.datepicker("setDate", Core.DateTime.Parse(that.model.getDate()));
                    }

                    $(".ui-datepicker").wrap('<div class="jqueryUIcontrols" />');

                    var defaultOptions = {
                        template: 'dropdown'
                        , minuteStep: 1
                        , secondStep: 1
                        , showSeconds: true
                        , defaultTime: false
                        , showMeridian: false
                    };
                    that.options.MYREFERENCES.timePicker = that.$("#datetime_timePicker").timepicker(defaultOptions);
                    that.setTimePickerValue(that.model.getTime());
                    that.options.MYREFERENCES.timePicker.timepicker().on("changeTime.timepicker", that.timepicker_ev_changeTime);

                    if (that.options.MYREFERENCES.autoupdate.enabled)
                        that.start_autoupdate(); 

                    //appending view to the main container
                    thatContainer.append(that.$el);

                    if (callback && _.isFunction(callback))
                        callback.call(that, that); 

                }, false);
            });
        }
        , start_autoupdate: function () {
            if (this.options.MYREFERENCES.autoupdate.toid != null)
                clearTimeout(this.options.MYREFERENCES.autoupdate.toid);

            var d = new Date();
            var attrs = { date: null, time: null }; 
            attrs.date = Core.DateTime.ToString(d, "yyyy-mm-dd");
            attrs.time = Core.DateTime.ToString(d, "HH:MM:ss");

            if (this.options.MYREFERENCES.autoupdate.enabled)
                this.model.set(attrs);

            if (this.options.MYREFERENCES.autoupdate.enabled)
                this.options.MYREFERENCES.autoupdate.toid = setTimeout(this.start_autoupdate, 1000); 
        }
        , stop_autoupdate: function () {
            this.options.MYREFERENCES.autoupdate.enabled = false;

            if (this.options.MYREFERENCES.autoupdate.toid != null)
                clearTimeout(this.options.MYREFERENCES.autoupdate.toid);
        }
        , setTimePickerValue: function (newValue) {
            if (newValue)
                this.options.MYREFERENCES.timePicker.timepicker("setTime", this.model.getTime());
            else
                this.options.MYREFERENCES.timePicker.val('');
        }
        , dateModelChanged: function () {
            if (this.modelChanging == false) {
                if (this.options.MYREFERENCES.datePicker) {
                    if (Core.DateTime.ToString(this.options.MYREFERENCES.datePicker.datepicker("getDate"), "yyyy-mm-dd") != this.model.getDate())
                        this.options.MYREFERENCES.datePicker.datepicker("setDate", Core.DateTime.Parse(this.model.get("datetime")));
                }
            }
        }
        , timeModelChanged: function () {
            if (this.modelChanging == false) {
                if (this.options.MYREFERENCES.timePicker) {
                    if (this.options.MYREFERENCES.timePicker.data("timepicker").getFormattedTime("24") != this.model.getTime()) {
                        this.setTimePickerValue(this.model.getTime());
                    }
                }
            }
        }
        , calendarChanged: function () {
            var dateSelected = Core.DateTime.ToString(this.options.MYREFERENCES.datePicker.datepicker("getDate"), "yyyy-mm-dd");

            this.modelChanging = true;

            try {
                //Prevent issues if date input is empty.
                if ((dateSelected instanceof Error) == false) {
                    this.model.setDate(dateSelected);
                }
                else if (this.model.get('date')) {
                    this.model.setDate(null);
                }

            }
            finally {
                this.modelChanging = true;
            }
        }
        , timepicker_focus: function () {
            //stopping autoupdate cause the user tried to modify the time.
            if (this.options.MYREFERENCES.autoupdate.enabled)
                this.stop_autoupdate();

            this.options.MYREFERENCES.timepicker.isFocused = true;
        }
        , timepicker_ev_changeTime: function () {
            var isFocused = this.options.MYREFERENCES.timepicker.isFocused;
            if (!isFocused) {
                var timeSelected = this.options.MYREFERENCES.timePicker.data("timepicker").getFormattedTime("24");
                this.model.setTime(timeSelected);
            }
        }
        , timepicker_blur: function (params) {
            //var timeSelected = this.options.MYREFERENCES.timePicker.data("timepicker").getFormattedTime("24");
            //this.model.setTime(timeSelected);
            this.options.MYREFERENCES.timepicker.isFocused = false;

            var currentTextboxValue = $.trim(this.options.MYREFERENCES.timePicker.data("timepicker").$element.val());

            //This means that the time textbox is empty, but for some reason the widget does not fire event change.
            //So we manually check it to update our model.
            if ((currentTextboxValue.length == 0) && (this.model.get('time'))) {
                this.modelChanging = true;

                try {
                    this.model.setTime(null);
                }
                finally {
                    this.modelChanging = false;
                }
            }
        }
        , timepicker_onKeyDown: function (event) {
            if (event.which) {
                switch (event.which) {
                    //enter key
                    case 13:
                        this.options.MYREFERENCES.timePicker.blur();
                        break;
                        //escape key
                    case 27:
                        this.timeModelChanged();
                        this.options.MYREFERENCES.timePicker.blur();
                        break;
                };
            }
        }
        , calendar_onKeyDown: function (event) {
            if (event.which) {
                switch (event.which) {
                    //enter key
                    case 13:
                        this.options.MYREFERENCES.datePicker.blur();
                        break;
                        //escape key
                    case 27:
                        this.dateModelChanged();
                        this.options.MYREFERENCES.datePicker.blur();
                        break;
                };
            }
        }
        , setFocusTime: function () {
            try {
                this.$("#datetime_timePicker").focus();
            } catch (Error) { }
        }
        , calendarBeforeShow: function () {            
            if (this.options.MYREFERENCES.autoupdate.enabled)
                this.stop_autoupdate();
        }
        , showCalendar: function () {
            if (this.options.MYREFERENCES.autoupdate.enabled)
                this.stop_autoupdate();

            if (this.options.MYREFERENCES.datePicker.datepicker("widget").is(":visible"))
                this.options.MYREFERENCES.datePicker.datepicker("hide");
            else
                this.options.MYREFERENCES.datePicker.datepicker("show");
        }
        , showCalendarFocus: function () {
            //$("#calendar-icon-clickeable").click();
        }
        , _setSectionsLayout: function () {
            app.models.subnavbar.set("sections", "6-6");
        }

        , bindEvents: function () {
        }

        , unbindEvents: function () {
        }

        , close: function () {
            this.remove();
            this.unbindEvents();
            this.unbind();
        }
        , show: function () {
            this._setSectionsLayout();
            this.bindEvents();
            this.$el.show();
        }
        , hide: function () {
            this.unbindEvents();
            this.$el.hide();
        }
    });

    // Required, return the module for AMD compliance.
    return DateTimeControl;

});
