

var ImageChooser = function(config){
    this.config = config;
}

ImageChooser.prototype = {
    // cache data by image name for easy lookup
    lookup : {},
    
    show : function(el, callback) {
        if(!this.win){
            this.initTemplates();
            this.upload = new Ext.UploadWindow();
            this.store = new Ext.data.JsonStore({
                url: this.config.url,
                fields: [
                    'text', 'url', 'id',
                    {name:'size', type: 'float'},
                    {name:'lastmod', type:'date', dateFormat:'timestamp'}
                ],
                listeners: {
                    'load': {fn:function(){ 
                        this.view.select(0); 
                    }, scope:this, single:true}
                }
            });
            this.store.load();
            
            var formatSize = function(data){
                if(data.size < 1024) {
                    return data.size + " bytes";
                } else {
                    return (Math.round(((data.size*10) / 1024))/10) + " KB";
                }
            };
        
            var formatData = function(data){
                data.shortName = data.text.ellipse(15);
                data.sizeString = formatSize(data);
                data.dateString = new Date(data.lastmod).format("m/d/Y g:i a");
                this.lookup[data.id] = data;
                return data;
            };
            
            this.tb = new Ext.Toolbar({
                border: false,
                items:[{
                    text: 'New folder',
                    iconCls: 'icon-folder-add',
                    listeners: {
                        'click': {fn:this.onCreateNewFolder, scope:this}
                    }
                },{
                    text: 'Upload files',
                    iconCls: 'icon-upload',
                    listeners: {
                        'click': {fn:this.onUpload, scope:this}
                    }
                }]
            });
        
            this.tree = new Ext.tree.TreePanel({
                animate:true,
                enableDD:true,
                ddGroup: 'filemanagerDD',
                ddAppendOnly: true,
                border: false,
                containerScroll: true, 
                loader: new Ext.tree.TreeLoader({
                    dataUrl:'/file_manager/nodes'
                })
            });
            this.tree.getSelectionModel().on({
                 selectionchange:{scope:this, fn:function(model, node) {
                      this.store.load({params:{
                          node: node.id
                      }})
                 }}
            });
            this.tree.on('beforenodedrop', 
              function (e) {
                  alert(e);
              }
            );
            var root = new Ext.tree.AsyncTreeNode({
                text: 'File root',
                draggable: false,
                allowDrag: false,
                allowDrop: true,
                id:"root"
            });
            this.tree.setRootNode(root);
            
            this.treeEditor = new Ext.tree.TreeEditor(this.tree, {
                     allowBlank:false
                    ,cancelOnEsc:true
                    ,completeOnEnter:true
                    ,ignoreNoChange:true
                    ,selectOnFocus:true
            })  
            
            this.treeEditor.beforeNodeClick = function(node,e) {
                if (node && node.id == "root") {
                    // do not edit root
                    return true;
                } else {
                    // copied from Ext sources
                    clearTimeout(this.autoEditTimer);
                    if (this.tree.getSelectionModel().isSelected(node)){
                        e.stopEvent();
                        return this.triggerEdit(node);
                    } else {
                        return true;
                    }
                    
                }
            };

            // treeEditor event handlers
            this.treeEditor.on({
                     complete:{scope:this, fn:this.onTreeEditComplete}
            });
            
            this.view = new Ext.DataView({
                tpl: this.thumbTemplate,
                border: false,
                overClass:'x-view-over',
                itemSelector: 'div.thumb-wrap',
                multiSelect: true,
                store: this.store,
                plugins: [
                    new Ext.DataView.DragSelector({dragSafe:true})
                ],
                listeners: {
                    //'selectionchange': {fn:this.showDetails, scope:this, buffer:100},
                    'dblclick'       : {fn:this.doCallback, scope:this},
                    'loadexception'  : {fn:this.onLoadException, scope:this},
                    'beforeselect'   : {fn:function(view){
                        return view.store.getRange().length > 0;
                    }}
                },
                prepareData: formatData.createDelegate(this)
            });
            
            
            var cfg = {
                title: 'Choose an Image',
                id: 'img-chooser-dlg',
                layout: 'border',
                minWidth: 500,
                minHeight: 300,
                modal: false,
                constrainHeader: true,
                closeAction: 'hide',
                
                items:[{
                    id: 'img-chooser-view',
                    region: 'center',
                    title:'Files',
                    bodyBorder: false,
                    autoScroll: true,
                    items: this.view
                },{
                    id: 'img-tree-panel',
                    region: 'west',
                    title:'Folders',
                    bodyBorder: false,
                    width: 200,
                    split: true,
                    autoScroll: true,
                    items: this.tree
                }],
                tbar: this.tb,
                buttons: [{
                        text: 'Close',
                        handler: function(){ this.win.hide(); },
                        scope: this
                }],
                keys: {
                    key: 27, // Esc key
                    handler: function(){ this.win.hide(); },
                    scope: this
                }
            };
            Ext.apply(cfg, this.config);
            this.win = new Ext.Window(cfg);
        }
        this.reset();
        this.win.show(el);
        this.tree.render();
        if (root) {
            root.select();
            root.expand();
            root.fireEvent("selectionchange");
        }
        var zone = new ImageDragZone(this.view, {containerScroll:true, ddGroup: 'filemanagerDD'}); 
        //this.win.anchorTo(Ext.getBody(), "tl", [100,100], 400);
        this.callback = callback;
        this.animateTarget = el;
    },

    initTemplates : function(){
        this.thumbTemplate = new Ext.XTemplate(
            '<tpl for=".">',
            '<div class="thumb-wrap" id="{id}">',
            '<div class="thumb"><div class="image"><img src="{url}" title="{text}"></div></div>',
            '<span>{text}</span></div>',
            '</tpl>',
            '<div class="x-clear"></div>'
        );
        this.thumbTemplate.compile();
    },
    // Tree Node Editor
    onTreeEditComplete:function(editor, newName, oldName) {
        if(newName === oldName || editor.creatingNewDir) {
            editor.creatingNewDir = false;
            return;
        } 
        var options = {
                 url:"/file_manager/folder_renamed"
                ,method:"post"
                ,scope:this
                ,node:editor.editNode
                ,callback:this.cmdResult
                ,params:{
                    id: editor.editNode.id,
                    oldname: oldName,
                    newname: newName,
                    cmd: "renamedir"
                }
        };
        Ext.Ajax.request(options);
    },
    onUpload : function() {
        var node = this.tree.getSelectionModel().getSelectedNode();
        this.upload.upload(node, this.store);
    },
    onCreateNewFolder : function() {
        // new folder
        var treeEditor = this.treeEditor; 
        var node = this.tree.getSelectionModel().getSelectedNode();
        node.expand(false, false, function(n) {
            newNode = n.appendChild(new Ext.tree.AsyncTreeNode({
                text:"New folder", 
                iconCls:'folder'}));
            treeEditor.on({
                    complete:{
                             scope:this
                            ,single:true
                            ,fn:this.afterNewFolder
                    }}
            );
            // creating new directory flag
            treeEditor.creatingNewDir = true;

            // start editing
            //treeEditor.triggerEdit(newNode);
            (function(){treeEditor.triggerEdit(newNode);}.createDelegate(this).defer(10));
        // expand callback needs to run in this context
        }.createDelegate(this));
    },
    afterNewFolder:function(editor) {
        var options = {
                 url:"/file_manager/folder_added"
                ,method:"post"
                ,scope:this
                ,node:editor.editNode
                ,callback:this.cmdResult
                ,params:{
                    id: editor.editNode.parentNode.id,
                    newname: editor.editNode.text,
                    cmd: "newdir"
                }
        };
        Ext.Ajax.request(options);
    },
    cmdResult:function(options, success, response) {
        var o;

        if (success === true) {
            try {
                o = Ext.decode(response.responseText);
            } catch(ex) {
                this.showError(response.responseText);
            } 
            if (o.success !== true) {
                switch(options.params.cmd) {
                    case 'newdir':
                        options.node.parentNode.removeChild(options.node);
                        break;
                    case 'renamedir':
                        options.node.setText(options.params.oldname);
                        break;
                }
                this.showError(o.error);
            } else {
                switch(options.params.cmd) {
                    case 'newdir':
                        options.node.id = o.id;
                        break;
                }
            }
        }
    },
    showError:function(msg, title) {
       Ext.MessageBox.show({
                 title:title || "Error"
                ,msg:msg || "Unknown error"
                ,icon:Ext.MessageBox.ERROR
                ,buttons:Ext.MessageBox.OK
                ,minWidth:1200 > String(msg).length ? 360 : 600
        });
    },
    showDetails : function(){/*
        var selNode = this.view.getSelectedNodes();
        var detailEl = Ext.getCmp('img-detail-panel').body;
        if (selNode && selNode.length > 0) {
            selNode = selNode[0];
            Ext.getCmp('ok-btn').enable();
            var data = this.lookup[selNode.id];
            detailEl.hide();
            this.detailsTemplate.overwrite(detailEl, data);
            detailEl.slideIn('l', {stopFx:true,duration:.2});
        } else {
            Ext.getCmp('ok-btn').disable();
            detailEl.update('');
        }
    */},

    reset : function(){
        if(this.win.rendered){
            //Ext.getCmp('filter').reset();
            this.view.getEl().dom.scrollTop = 0;
        }
        //this.view.store.clearFilter();
        this.view.select(0);
    },

    doCallback : function(){
        var selNode = this.view.getSelectedNodes()[0];
        var callback = this.callback;
        var lookup = this.lookup;
        this.win.hide(this.animateTarget, function(){
            if(selNode && callback){
                var data = lookup[selNode.id];
                callback(data);
            }
        });
    },

    onLoadException : function(v,o){
        this.view.getEl().update('<div style="padding:10px;">Error loading images.</div>');
    }
};

String.prototype.ellipse = function(maxLength){
    if(this.length > maxLength){
        return this.substr(0, maxLength-3) + '...';
    }
    return this;
};
