/*---------------------------------------------------------
 * OpenERP web_gantt
 *---------------------------------------------------------*/
openerp.web_gantt = function (instance) {
var _t = instance.web._t,
   _lt = instance.web._lt;
var QWeb = instance.web.qweb;
instance.web.views.add('gantt', 'instance.web_gantt.GanttView');

instance.web_gantt.GanttView = instance.web.View.extend({
    display_name: _lt('Gantt'),
    template: "GanttView",
    view_type: "gantt",
    init: function() {
        var self = this;
        this._super.apply(this, arguments);
        this.has_been_loaded = $.Deferred();
        this.chart_id = _.uniqueId();
    },
    view_loading: function(r) {
        return this.load_gantt(r);
    },
    load_gantt: function(fields_view_get, fields_get) {
        var self = this;
        this.fields_view = fields_view_get;
        this.$el.addClass(this.fields_view.arch.attrs['class']);
        return self.alive(new instance.web.Model(this.dataset.model)
            .call('fields_get')).then(function (fields) {
                self.fields = fields;
                self.has_been_loaded.resolve();
            });
    },
    do_search: function (domains, contexts, group_bys) {
        var self = this;
        self.last_domains = domains;
        self.last_contexts = contexts;
        self.last_group_bys = group_bys;
        // select the group by
        var n_group_bys = [];
        if (this.fields_view.arch.attrs.default_group_by) {
            n_group_bys = this.fields_view.arch.attrs.default_group_by.split(',');
        }
        if (group_bys.length) {
            n_group_bys = group_bys;
        }
        // gather the fields to get
        var fields = _.compact(_.map(["date_start", "date_delay", "date_stop", "progress"], function(key) {
            return self.fields_view.arch.attrs[key] || '';
        }));
        fields = _.uniq(fields.concat(n_group_bys));
        
        return $.when(this.has_been_loaded).then(function() {
            return self.dataset.read_slice(fields, {
                domain: domains,
                context: contexts
            }).then(function(data) {
                return self.on_data_loaded(data, n_group_bys);
            });
        });
    },
    reload: function() {
        if (this.last_domains !== undefined)
            return this.do_search(this.last_domains, this.last_contexts, this.last_group_bys);
    },
    on_data_loaded: function(tasks, group_bys) {
        var self = this;
        var ids = _.pluck(tasks, "id");
        return this.dataset.name_get(ids).then(function(names) {
            var ntasks = _.map(tasks, function(task) {
                return _.extend({__name: _.detect(names, function(name) { return name[0] == task.id; })[1]}, task); 
            });
            return self.on_data_loaded_2(ntasks, group_bys);
        });
    },
    on_data_loaded_2: function(tasks, group_bys) {
        var self = this;
        $(".oe_gantt", this.$el).html("");

        //prevent more that 1 group by
        if (group_bys.length > 0) {
            group_bys = [group_bys[0]];
        }
        // if there is no group by, simulate it
        if (group_bys.length == 0) {
            group_bys = ["_pseudo_group_by"];
            _.each(tasks, function(el) {
                el._pseudo_group_by = "Gantt View";
            });
            this.fields._pseudo_group_by = {type: "string"};
        }
        
        // get the groups
        var split_groups = function(tasks, group_bys) {
            if (group_bys.length === 0)
                return tasks;
            var groups = [];
            _.each(tasks, function(task) {
                var group_name = task[_.first(group_bys)];
                var group = _.find(groups, function(group) { return _.isEqual(group.name, group_name); });
                if (group === undefined) {
                    group = {name:group_name, tasks: [], __is_group: true};
                    groups.push(group);
                }
                group.tasks.push(task);
            });
            _.each(groups, function(group) {
                group.tasks = split_groups(group.tasks, _.rest(group_bys));
            });
            return groups;
        }
        var groups = split_groups(tasks, group_bys);
        
        // track ids of task items for context menu
        var task_ids = {};
        // creation of the chart
        var generate_task_info = function(task, plevel) {
            if (_.isNumber(task[self.fields_view.arch.attrs.progress])) {
                var percent = task[self.fields_view.arch.attrs.progress] || 0;
            } else {
                var percent = 100;
            }
            var level = plevel || 0;
            if (task.__is_group) {
                var task_infos = _.compact(_.map(task.tasks, function(sub_task) {
                    return generate_task_info(sub_task, level + 1);
                }));
                if (task_infos.length == 0)
                    return;
                var task_start = _.reduce(_.pluck(task_infos, "task_start"), function(date, memo) {
                    return memo === undefined || date < memo ? date : memo;
                }, undefined);
                var task_stop = _.reduce(_.pluck(task_infos, "task_stop"), function(date, memo) {
                    return memo === undefined || date > memo ? date : memo;
                }, undefined);
                var duration = (task_stop.getTime() - task_start.getTime()) / (1000 * 60 * 60);
                var group_name = task.name ? instance.web.format_value(task.name, self.fields[group_bys[level]]) : "-";
                if (level == 0) {
                    var group = new GanttProjectInfo(_.uniqueId("gantt_project_"), group_name, task_start);
                    _.each(task_infos, function(el) {
                        group.addTask(el.task_info);
                    });
                    return group;
                } else {
                    var group = new GanttTaskInfo(_.uniqueId("gantt_project_task_"), group_name, task_start, duration || 1, percent);
                    _.each(task_infos, function(el) {
                        group.addChildTask(el.task_info);
                    });
                    return {task_info: group, task_start: task_start, task_stop: task_stop};
                }
            } else {
                var task_name = task.__name;
                var duration_in_business_hours = false;
                var task_start = instance.web.auto_str_to_date(task[self.fields_view.arch.attrs.date_start]);
                if (!task_start)
                    return;
                var task_stop;
                if (self.fields_view.arch.attrs.date_stop) {
                    task_stop = instance.web.auto_str_to_date(task[self.fields_view.arch.attrs.date_stop]);
                    if (!task_stop)
                        task_stop = task_start;
                } else { // we assume date_duration is defined
                    var tmp = instance.web.format_value(task[self.fields_view.arch.attrs.date_delay],
                        self.fields[self.fields_view.arch.attrs.date_delay]);
                    if (!tmp)
                        return;
                    task_stop = task_start.clone().addMilliseconds(instance.web.parse_value(tmp, {type:"float"}) * 60 * 60 * 1000);
                    duration_in_business_hours = true;
                }
                var duration = (task_stop.getTime() - task_start.getTime()) / (1000 * 60 * 60);
                var id = _.uniqueId("gantt_task_");
                if (!duration_in_business_hours){
                    duration = (duration / 24) * 8;
                }
                var task_info = new GanttTaskInfo(id, task_name, task_start, (duration) || 1, percent);
                task_info.internal_task = task;
                task_ids[id] = task_info;
                return {task_info: task_info, task_start: task_start, task_stop: task_stop};
            }
        }
        var gantt = new GanttChart();
        _.each(_.compact(_.map(groups, function(e) {return generate_task_info(e, 0);})), function(project) {
            gantt.addProject(project);
        });
        gantt.setEditable(true);
        gantt.setImagePath("/web_gantt/static/lib/dhtmlxGantt/codebase/imgs/");
        gantt.attachEvent("onTaskEndDrag", function(task) {
            self.on_task_changed(task);
        });
        gantt.attachEvent("onTaskEndResize", function(task) {
            self.on_task_changed(task);
        });
        gantt.create(this.chart_id);
        
        // bind event to display task when we click the item in the tree
        $(".taskNameItem", self.$el).click(function(event) {
            var task_info = task_ids[event.target.id];
            if (task_info) {
                self.on_task_display(task_info.internal_task);
            }
        });
        if (this.is_action_enabled('create')) {        
            // insertion of create button
            var td = $($("table td", self.$el)[0]);
            var rendered = QWeb.render("GanttView-create-button");
            $(rendered).prependTo(td);
            $(".oe_gantt_button_create", this.$el).click(this.on_task_create);
        }
        // Fix for IE to display the content of gantt view.
        this.$el.find(".oe_gantt td:first > div, .oe_gantt td:eq(1) > div > div").css("overflow", "");
    },
    on_task_changed: function(task_obj) {
        var self = this;
        var itask = task_obj.TaskInfo.internal_task;
        var start = task_obj.getEST();
        var duration = task_obj.getDuration();
        var duration_in_business_hours = !!self.fields_view.arch.attrs.date_delay;
        if (!duration_in_business_hours){
            duration = (duration / 8 ) * 24;
        }
        var end = start.clone().addMilliseconds(duration * 60 * 60 * 1000);
        var data = {};
        data[self.fields_view.arch.attrs.date_start] =
            instance.web.auto_date_to_str(start, self.fields[self.fields_view.arch.attrs.date_start].type);
        if (self.fields_view.arch.attrs.date_stop) {
            data[self.fields_view.arch.attrs.date_stop] = 
                instance.web.auto_date_to_str(end, self.fields[self.fields_view.arch.attrs.date_stop].type);
        } else { // we assume date_duration is defined
            data[self.fields_view.arch.attrs.date_delay] = duration;
        }
        this.dataset.write(itask.id, data);
    },
    on_task_display: function(task) {
        var self = this;
        var pop = new instance.web.form.FormOpenPopup(self);
        pop.on('write_completed',self,self.reload);
        pop.show_element(
            self.dataset.model,
            task.id,
            null,
            {}
        );
    },
    on_task_create: function() {
        var self = this;
        var pop = new instance.web.form.SelectCreatePopup(this);
        pop.on("elements_selected", self, function() {
            self.reload();
        });
        pop.select_element(
            self.dataset.model,
            {
                initial_view: "form",
            }
        );
    },
});

};
