/// <reference path="../../js/Ext-lib/ext-base-debug.js"/>
/// <reference path="../../js/Ext-lib/ext-all-debug.js"/>

Ext.ns('App');

Ext.onReady(function() {
    Ext.BLANK_IMAGE_URL = 'http://extjs.cachefly.net/ext-3.1.0/resources/images/default/s.gif';
    Ext.QuickTips.init();
    
    if (typeof console === 'undefined') {
        console = {
            log : Ext.log,
            error : Ext.log
        };
    }
    App.Scheduler.init();
});


App.Scheduler = {
    
    reloadChartData : function() {
        var resourceStore = this.grid.store,
            eventStore = this.grid.eventStore,
            data = [],
            start = this.grid.getStart(),
            end = this.grid.getEnd(),
            viewTimeSpan = end - start;
                 
        resourceStore.each(function(r) {
            var totalTime = 0;
            eventStore.queryBy(function(eRec) {
                if (eRec.get('ResourceId') === r.get('Id') && Date.intersectSpans(start, end, eRec.get('StartDate'), eRec.get('EndDate'))) {
                   totalTime += Date.min(eRec.get('EndDate'), end) - Date.max(eRec.get('StartDate'), start); 
                }
            });
            
            data.push({
                name : r.get('Name'),
                usage : Math.round(100 * totalTime / viewTimeSpan)
            });
        });
        
        this.chartPanel.setTitle(String.format('Machine utilization levels for {0} - {1}', start.format('Y-m-d'), end.format('Y-m-d')));
        this.chartStore.loadData(data);
    },
    
    // Initialize application
    init : function() {        
        var start = new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate()),
            end = start.add(Date.DAY, 7);
            
        this.grid = this.createGrid();
        this.grid.setView(start, end, 'day', Sch.ViewBehaviour.DayView, this.renderer);
        
        this.grid.on('eventcontextmenu', this.onEventContextMenu, this);
        
        this.grid.on('eventclick', function(g, rec, node, e) {
            if (Ext.fly(e.getTarget()).is('img.saveChanges')) {
                Ext.fly(e.getTarget('.sch-eventtools')).hide();
                var el = Ext.get(e.getTarget('.sch-event'));
                el.move('down', 1, {
                    duration : 0.1,
                    callback : function() {
                        el.move('up', 1, {
                            duration : 0.1,
                            callback : function() {
                                rec.commit();
                            }
                        });
                    }
                });
            } else if (Ext.fly(e.getTarget()).is('img.rejectChanges')) {
                rec.reject();
            }
        });
        
        this.initStoreEvents();
        
        var es = this.grid.eventStore;
        
        // Load resource data
        this.grid.store.loadData([
                {Id : 'r1', Name : 'Machine 1', Category : 'Machines'},
                {Id : 'r2', Name : 'Machine 2', Category : 'Machines'},
                {Id : 'r3', Name : 'Machine 3', Category : 'Machines'},
                {Id : 'r10', Name : 'Robot 1', Category : 'Robots'},
                {Id : 'r11', Name : 'Robot 2', Category : 'Robots'},
                {Id : 'r12', Name : 'Robot 3', Category : 'Robots'}
        ]);
        
        var today = new Date();
        today.clearTime();
        
        // Load event data
        es.loadData([
                {Id : 'e1', ResourceId: 'r1', Title : 'Short event', StartDate : today.add(Date.HOUR, 2), EndDate : today.add(Date.HOUR, 6)},
                {Id : 'e2', ResourceId: 'r2', Title : 'Little bit longer', StartDate : today.add(Date.HOUR, 6), EndDate : today.add(Date.DAY, 1)},
                {Id : 'e3', ResourceId: 'r3', Title : 'Even longer', StartDate : today.add(Date.HOUR, 8), EndDate : today.add(Date.DAY, 2)},
                {Id : 'e6', ResourceId: 'r10', Title : 'Little bit longer', StartDate : today.add(Date.HOUR, 6), EndDate : today.add(Date.DAY, 1)},
                {Id : 'e7', ResourceId: 'r11', Title : 'Even longer', StartDate : today.add(Date.HOUR, 8), EndDate : today.add(Date.DAY, 2)},
                {Id : 'e8', ResourceId: 'r12', Title : 'Loooong event', StartDate : today.add(Date.HOUR, 10), EndDate : today.add(Date.DAY, 3)}
        ]);
        
        this.chartStore = new Ext.data.JsonStore({
            fields:['name', 'usage'],
            data : []
        });

        this.chartPanel = new Ext.Panel({
            width: 700,
            height: 300,
            renderTo: 'chart-local',
            title: 'Machine utilization levels',
            items: {
                xtype: 'columnchart',
                store: this.chartStore,
                yField: 'usage',
	            url: 'http://extjs.cachefly.net/ext-3.1.0/resources/charts.swf',
                xField: 'name',
                xAxis: new Ext.chart.CategoryAxis({
                    title: 'Machine'
                }),
                yAxis: new Ext.chart.NumericAxis({
                    title: '% Usage ',
                    displayName: 'usage',
                    labelRenderer : Ext.util.Format.numberRenderer('0'),
                    minimum: 0,
                    maximum: 100
                }),
                tipRenderer : function(chart, record){
                    return record.data.usage + ' %';
                },
                extraStyle: {
                   xAxis: {
                        labelRotation: -90
                    }
                }
            }
        });
        
        this.grid.on('viewchange', this.reloadChartData, this);
        
        this.reloadChartData();
    },
    
    initStoreEvents : function() {
        var g = this.grid;
        
        g.eventStore.on({
            'add' : this.reloadChartData,
            'update' : this.reloadChartData,
            'remove' : this.reloadChartData,
            scope : this
        });
    },
    
    // Default renderer, supplies data to be applied to the event template
    renderer : function (event, r, row, col, ds) {
        // Not showing any information inside the events for this demo
        return {
            cls : 'evt-' + r.get('Category')
        };
    },
    
    onEventContextMenu : function(g, rec, e) {
        e.stopEvent();
        
        if (!g.gCtx) {
            g.gCtx = new Ext.menu.Menu({
                items : [
                    {
                        id : 'context-delete',
                        text : 'Delete event',
                        iconCls : 'icon-delete'
                    }
                ]
            });
            
            g.gCtx.on('itemclick', function(item, e) {
                switch (item.id) {
                    case 'context-delete':
                        g.eventStore.remove(g.gCtx.rec);
                    break;
                    
                    default:
                        throw item.id + ' is not a valid menu action';
                    break;
                }
            }, this);
        }
        g.gCtx.rec = rec;
        g.gCtx.showAt(e.getXY());
    },
    
    createGrid : function() {
        
        // Store holding all the resources
        var resourceStore = new Ext.data.GroupingStore({
            groupField : 'Category',
            sortInfo:{field: 'Id', direction: "ASC"},
            reader : new Ext.data.JsonReader({
                idProperty : 'Id'
            }, [
                    'Id', 
                    'Category',
                    'Name'
                ]
            )
        });
        
        // Store holding all the events
        var eventStore = new Ext.data.JsonStore({
            sortInfo:{field: 'ResourceId', direction: "ASC"},
            idProperty : 'Id',
            fields : [
                {name: 'Id', type:'string'},
                {name: 'ResourceId'},
                {name: 'Title'},
                {name: 'StartDate', type : 'date'},
                {name: 'EndDate', type : 'date'}
            ]
        });
        
        var g = new Sch.SchedulerPanel({
            height : 300,
            width : 700,
            renderTo : 'grid-local',
            enabledHdMenu : false,
            
            createValidatorFn : function(resourceRecord, start, end) {
                return Date.getDurationInDays(start, end) <= 3;
            },
            
            resizeValidatorFn : function(resourceRecord, eventRecord, start, end) {
                return Date.getDurationInDays(start, end) <= 3;
            },
            
            dndValidatorFn : function(dragEventRecords, targetRowRecord) {
                // Only allow drops on the same row
                return dragEventRecords[0].get('ResourceId') === targetRowRecord.get('Id');
            },
                    
            // Setup your static columns
            colModel : new Ext.ux.grid.LockingColumnModel({
                columns : [
                   {header : 'Machines', sortable:true, width:140, dataIndex : 'Name', locked:true, renderer : function(v, m, r) {
                      m.css = r.get('Category');
                      return v;
                   }}
                ]
            }),
            
            view: new Sch.LockingSchedulerView({
                cellSelectorDepth:7
            }),
            
            // Override default event template to include the resize handle
            eventTemplate : new Ext.Template(
                '<div id="{id}" style="width:{width}px;left:{leftOffset}px" class="sch-event {cls}">',
                    String.format(Sch.SchedulerPanel.prototype.resizeHandleHtml, 'west'),
                    '<div class="sch-eventtools"><img class="rejectChanges" ext:qtip="Reject changes" src="images/cancel.png"/><img class="saveChanges" ext:qtip="Save changes" src="images/bullet_disk.png"/></div>',
                    '<div class="sch-event-inner">{text}</div>',
                    String.format(Sch.SchedulerPanel.prototype.resizeHandleHtml, 'east'),
                '</div>'
            ).compile(),
            
            store : resourceStore,
            eventStore : eventStore,
            border : true,
            
            tbar : [
                {
                    iconCls : 'icon-prev',
                    scale : 'medium',
                    handler : function() {
                        var start, oldStart = g.getStart();
                        
                        start = oldStart.add(Date.DAY, -Date.getDurationInDays(oldStart, g.getEnd()));
                        g.setView(start, oldStart);
                    }
                },
                '            ',
                {
                    id : 'span2',
                    enableToggle : true,
                    text: '1 week',
                    toggleGroup: 'span',
                    pressed:true,
                    handler : function() {
                        var s = g.getStart();
                        while (s.getDay() != 1) {
                            s = s.add(Date.DAY, -1);
                        }
                        g.setView(s, s.add(Date.DAY, 7), 'day', Sch.ViewBehaviour.DayView);
                    }
                },
                '            ',
                {
                    id : 'span3',
                    enableToggle : true,
                    text: '6 weeks',
                    toggleGroup: 'span',
                    handler : function() {
                        var s = g.getStart();
                        while (s.getDay() != 1) {
                            s = s.add(Date.DAY, -1);
                        }
                        g.setView(s, s.add(Date.DAY, 42), 'week', Sch.ViewBehaviour.WeekView);
                    }
                },
                '->',
                {
                    iconCls : 'icon-next',
                    scale : 'medium',
                    handler : function() {
                        var end, oldEnd = g.getEnd();
                        end = oldEnd.add(Date.DAY, Date.getDurationInDays(g.getStart(), oldEnd));
                        
                        g.setView(oldEnd, end);
                    }
                }
            ],
            
            listeners : {
                dragcreateend : {
                    fn : function(p, data, e) {
                        var b = new this.grid.eventStore.recordType({
                            Id : nextId(),
                            Title: '', 
                            ResourceId : data.record.get('Id'),
                            StartDate : data.startDate,
                            EndDate : data.endDate
                        });
                        
                        this.grid.eventStore.add(b);
                    },
                    scope : this
                }
            },
            
            trackMouseOver : false
        });
        
        return g;
    }
};

var nextId = function(){
	// if the time isn't unique enough, the addition 
	// of random chars should be
	var t = String(new Date().getTime()).substr(4);
	var s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
	for(var i = 0; i < 4; i++){
		t += s.charAt(Math.floor(Math.random()*26));
	}
	return 'e' + t;
};