/* <copyright>
Copyright (c) 2012, Motorola Mobility LLC.
All Rights Reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice,
  this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of Motorola Mobility LLC nor the names of its
  contributors may be used to endorse or promote products derived from this
  software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
</copyright> */

var Montage = require("montage/core/core").Montage,
    Component = require("montage/ui/component").Component,
    iconsListModule = require("js/components/ui/icon-list-basic/iconsList.reel"),
    treeModule = require("js/components/ui/tree-basic/tree.reel");

var PickerNavigator = exports.PickerNavigator = Montage.create(Component, {

    filterVal: {
        value: null,
        serializable: true
    },

    error: {
        value: null,
        serializable: true
    },

    addressBarUri: {
        value: null,
        serializable: true
    },

    forwardArrow: {
        value: null,
        serializable: true
    },

    backArrow: {
        value: null,
        serializable: true
    },

    leftNav: {
        value: null,
        serializable: true
    },

    iconViewContainer: {
        value: null,
        serializable: true
    },

    iconView: {
        value: null,
        serializable: true
    },

    treeView: {
        value: null,
        serializable: true
    },

    treeViewContainer: {
        value: null,
        serializable: true
    },

    okButton: {
        value: null,
        serializable: true
    },

    metadataSection: {
        value: null,
        serializable: true
    },

    filters: {
        value: null,
        serializable: true
    },

    refreshButton: {
        value: null,
        serializable: true
    },

    cancelButton: {
        value: null,
        serializable: true
    },

    resultsArea: {
        value: null,
        serializable: true
    },

    popup:{
        enumerable: false,
        writable: true,
        value: null
    },

    mainContentData:{
        enumerable:false,
        writable:true,
        value:null
    },

    _firstTime: {
        enumerable: false,
        value: true
    },

    firstTime:{
        get: function(){},
        set: function(){}
    },

    pickerCallback:{
        enumerable:false,
        writable:true,
        value:null
    },

    selectedItems:{//passed to pickerCallback on click of OK
        enumerable:false,
        writable:true,
        value:[]
    },

    /**
     * store a reference to the currently selected node... for single selection
     */
     currentSelectedNode:{
        enumerable:false,
        writable:true,
        value:null
    },

    currentURI:{
        enumerable:false,
        writable:true,
        value:null
    },

    iconsViewDrawnOnce:{
        enumerable:false,
        writable:true,
        value:false
    },

    /**
     * for tree view only
     * will store folder uri vs tree instance map
     */
    treeRefHash:{
        enumerable:false,
        writable:true,
        value:{

        }
    },

    selectedPickerView:{
        enumerable:false,
        writable:true,
        value:null
    },

    /**
     * Contains the different Views and their update handlers
     */
    pickerViews:{
        enumerable:false,
        writable:true,
        value: function(){
            var that = this;
            return {
                "iconView":that.updateIconView,
                "treeView":that.updateTreeView
            }
        }
    },

    pickerModel:{
        enumerable:false,
        writable:true,
        value:null
    },

    willDraw: {
        enumerable: false,
        value: function() {

        }
    },
    draw: {
        enumerable: false,
        value: function() {
            this.filterVal.innerHTML = this.pickerModel.currentFilter;

            if(this.pickerModel.fatalError !== null){
                this.error.innerHTML = this.pickerModel.fatalError;
            }

        }
    },
    didDraw: {
        enumerable: false,
        value: function() {

            var that = this;
            this.iconList = null;
            this.newContent = null;
            this.spanEl = null;

            this.addIdentifiers();

            var topLevelDirs = this.pickerModel.topLevelDirectories;
            var leftNav = this.leftNav;
            //draw left nav
            if(!!topLevelDirs
                && (typeof topLevelDirs === "object")
                && ('splice' in topLevelDirs)
                && ('join' in topLevelDirs)
                &&(topLevelDirs.length > 0)){

                topLevelDirs.forEach(function(dirObj){
                    var newDiv = document.createElement("div");
                    newDiv.className = "driversList";
                    newDiv.innerHTML = dirObj.name;
                    leftNav.appendChild(newDiv);
                    if(dirObj.uri === this.pickerModel.currentRoot){
                        newDiv.classList.add("highlighted");
                        //enable ok for logical drive selections, when in directory selection mode
                        if(this.pickerModel.inFileMode === false){
                            this.okButton.removeAttribute("disabled");
                            //put into selectedItems..currently single selection is supported
                            this.selectedItems = [dirObj.uri];
                        }
                    }

                    newDiv.addEventListener("click", function(evt){that.handleTopLevelDirectoryClicks(evt, dirObj);}, false);
                }, that);
            }else{
                console.error("need at least 1 valid top level directory");
            }

            //Draw icon view list
            //TODO: check the default view and draw the appropriate view
            if(this.mainContentData !== null){

                this.currentURI = this.pickerModel.currentRoot;

                //draw the IconsList if icons view container is on
                if(this.iconViewContainer.style.display === "block"){
                    this.iconList = iconsListModule.IconsList.create();
                    //console.log(this.mainContentData);
                    this.iconList.iconsViewDataObject = this.mainContentData;
                    this.iconList.element = this.iconViewContainer;
                    this.iconList.needsDraw = true;
                    this.iconsViewDrawnOnce = true;
                    this.selectedPickerView = "iconView";

                    if(!this.iconView.classList.contains("viewSelected")){
                        this.iconView.classList.add("viewSelected")
                    }
                    if(this.treeView.classList.contains("viewSelected")){
                        this.treeView.classList.remove("viewSelected");
                    }

                }else if(this.treeViewContainer.style.display === "block"){
                    //else draw the Tree if tree view container is on
                    this.renderTree(this.treeViewContainer, this.currentURI);
                    this.selectedPickerView = "treeView";

                    if(!this.treeView.classList.contains("viewSelected")){
                        this.treeView.classList.add("viewSelected")
                    }
                    if(this.iconView.classList.contains("viewSelected")){
                        this.iconView.classList.remove("viewSelected");
                    }
                }

                this.updateAddressBar(this.pickerModel.currentRoot);
                this.pickerModel.storeHistory(this.pickerModel.currentRoot);//populate history

                this.updateMetadata(this.currentURI);

                //for directory selection, selected url is the folder entered
                if(!this.pickerModel.inFileMode ){
                    this.okButton.removeAttribute("disabled");
                    //put into selectedItems..currently single selection is supported
                    this.selectedItems = [this.pickerModel.currentRoot];
                }
            }

            this.element.addEventListener("openFolder", function(evt){that.handlePickerNavOpenFolder(evt);}, false);//add icon double click event listener to reload iconList with new set of data
            this.element.addEventListener("selectedItem", function(evt){that.handlePickerNavSelectedItem(evt);}, false);//for single selection only
            this.element.addEventListener("selectFile", function(evt){that.handlePickerNavSelectedFile(evt);}, false);//for file selection
            this.element.addEventListener("showMetadata", function(evt){that.handlePickerNavShowMetadata(evt);}, false);//show metadata on hover of icon
            this.element.addEventListener("updateMetadata", function(evt){that.handlePickerNavUpdateMetadata(evt);}, false);//show metadata on click of icon
            //this.addressGo.addEventListener("click", this, false);
            this.addressBarUri.addEventListener("keydown", this, false);
            this.addressBarUri.addEventListener("keyup", this, false);
            this.refreshButton.addEventListener("click", this, false);//refresh - gets from file system directly
            this.backArrow.addEventListener("click", this, false);
            this.forwardArrow.addEventListener("click", this, false);

            //populate filters if in file selection mode
            if(this.pickerModel.inFileMode === true){
                var filtersDD = this.element.querySelector(".filters .dropdown");
                if(!!this.pickerModel.fileFilters
                    && (typeof this.pickerModel.fileFilters === "object")
                    && ('splice' in this.pickerModel.fileFilters)
                    && ('join' in this.pickerModel.fileFilters)){
                    this.pickerModel.fileFilters.forEach(function(aFilter){
                        var newDiv = document.createElement("div");
                        newDiv.innerHTML = aFilter;
                        filtersDD.appendChild(newDiv);
                        newDiv.addEventListener("click", function(evt){that.handleFilterClick(evt, aFilter, filtersDD)}, false);
                    }, this);
                }

                var renderedWidth = this.getComputedWidth(filtersDD);
                this.filters.style.width = "" + (parseInt((renderedWidth.substring(0, (renderedWidth.length - 2)))) + 20) + "px";
            }else{
                this.filters.style.display = "none";
            }
            /**
             * attach click event listeners to the addressbar dropdown arrows
             */
            var dropDownArrows = this.element.getElementsByClassName("dropdownArrow");
            for(var x=0; x<dropDownArrows.length;x++){
                dropDownArrows[x].addEventListener("click", function(evt){that.handleAddressDropdownArrowClick(evt);}, false);
            }

            this.iconView.addEventListener("click", this, false);
            this.treeView.addEventListener("click", this, false);
            this.element.addEventListener("drawTree", function(evt){that.handlePickerNavDrawTree(evt);}, false);
            this.element.addEventListener("refreshTreeSegment", function(evt){that.handlePickerNavRefreshTreeSegment(evt);}, false);
            this.resultsArea.addEventListener("click", function(evt){that.handleResultsAreaClick(evt);}, false);
            this.element.addEventListener("click", function(evt){that.handlePickerNavClick(evt);}, false);
            this.okButton.addEventListener("click", function(evt){that.handleOkButtonAction(evt);}, false);
            this.cancelButton.addEventListener("click", function(evt){that.handleCancelButtonAction(evt);}, false);

            this.element.addEventListener("keyup", function(evt){
                if(evt.keyCode == 27) {
                    if(that.application.ninja.filePickerController.pickerNavChoices !== null){
                        that.handleCancelButtonAction();
                    }
                }
            }, true);

            //ready to show picker now
            this.element.style.visibility = "visible";
            this.element.focus();
        }
    },

    updateAddressBar:{
        writable: false,
        enumerable:true,
        value: function(folderUri){
            var addressBarEl = this.addressBarUri;
            if(addressBarEl){
                addressBarEl.value = folderUri;

                //update left drive selection

            }
        }
    },

    cleanupUri:{
        writable: false,
        enumerable:true,
        value: function(folderUri){
            folderUri = folderUri.replace(/^\s+|\s+$/g,"");  // strip any leading or trailing spaces
            //remove unnecessary / from end - for Win and Mac .... don't trim for the root
            if(((folderUri.charAt(folderUri.length - 1) === "/") || (folderUri.charAt(folderUri.length - 1) === "\\")) && (folderUri !== "/")){
                folderUri = folderUri.substring(0, (folderUri.length - 1));
                //console.log("*** new uri = "+ folderUri);
            }

            return folderUri;
        }
    },

    clearSelection:{
        writable: false,
        enumerable:true,
        value: function(folderUri){
            if((this.currentSelectedNode !== null) && (this.currentSelectedNode.classList.contains("selected"))){
                this.currentSelectedNode.classList.remove("selected");
            }
            this.currentSelectedNode = null;
            //disable OK
            if(!this.okButton.hasAttribute("disabled")){
                this.okButton.setAttribute("disabled", "true");
            }
        }
    },

    toggleDropdown:{
        writable: false,
        enumerable:true,
        value: function(dropdownArrowEl){
            var dropdownDiv = dropdownArrowEl.parentNode.getElementsByClassName("dropdown")[0];
            dropdownDiv.classList.toggle("hide");
        }
    },

    closeDropdowns:{
        writable:false,
        enumerable:true,
        value:function(clickedTarget){
            if(!clickedTarget.classList.contains("dropdownArrow")){//if not clicked on the drop down arrow itself
                var dropDowns = this.element.getElementsByClassName("dropdown");
                for(var x=0; x<dropDowns.length;x++){
                    if(!dropDowns[x].classList.contains("hide")){//if dropdown open
                        if(this.isOutside(dropDowns[x], clickedTarget)){
                            dropDowns[x].classList.add("hide");
                            //console.log("!!! closed DD: "+dropDowns[x].classList.toString());
                        }
                    }
                }
            }
        }
    },

    prepareAddressDropdownData:{
        writable:false,
        enumerable:true,
        value:function(uri){
            uri = this.cleanupUri(uri);
            var arr = [];
            var temp = new String(uri);
            while(temp.indexOf("/") != -1){

                if(""+temp === this.pickerModel.currentLogicalDrive){//stop at the logical drive
                    break;
                }

                temp = temp.substring(0, temp.lastIndexOf("/"));

                //populate dropdown irrespective of validity
//                if(!!this.application.ninja.filePickerController._directoryContentCache[temp]){//check if it is a valid location
//                    arr.push(temp);
//                }else{
//                    break;
//                }
                if(temp.length >0){
                    arr.push(temp);
                }else{//for unix root /
                    arr.push("/");
                }

            }
            //console.log(arr);
            return arr;
        }
    },

    renderTree:{
        writable:false,
        enumerable:true,
        value:function(element, uri){
            if(!!element){
                var tree = treeModule.Tree.create();
                tree.treeViewDataObject = this.application.ninja.filePickerController.prepareContentList(uri, this.pickerModel);
                //console.log("renderTree() for "+ uri);
                //console.log(tree.treeViewDataObject);
                tree.element = element;
                tree.needsDraw = true;
            }
        }
    },

    updateIconView:{
        writable:false,
        enumerable:true,
        value:function(uri, fromCache){
            var status = true;
            var iconViewContainer = this.element.querySelector(".iconViewContainer");
            if((typeof fromCache === 'undefined') || (fromCache === true)){
            this.newContent = this.application.ninja.filePickerController.prepareContentList(uri, this.pickerModel);
            }
            else{
                this.newContent = this.application.ninja.filePickerController.prepareContentList(uri, this.pickerModel, false);
            }
            if(!!this.newContent && this.newContent.length > 0){
                //clear selection
                this.clearSelection();
                this.spanEl = iconViewContainer.querySelector(".noResults");
                if(!!this.spanEl){
                    this.spanEl.style.display = "none";
                }
                this.iconList.iconsViewDataObject = this.newContent;
            }else{
                this.iconList.iconsViewDataObject = [];
                this.spanEl = iconViewContainer.querySelector(".noResults");
                if(!!this.spanEl){
                    this.spanEl.style.display = "block";
                }else{
                    this.spanEl = document.createElement("span");
                    this.spanEl.className = "noResults";
                    this.spanEl.innerHTML = "no results";
                    this.spanEl.style.display = "block";
                    iconViewContainer.appendChild(this.spanEl);
                }
                status = false; //for no match
            }
            this.updateMetadata(uri);

            return status;
        }
    },

    updateTreeView:{
        writable:false,
        enumerable:true,
        value:function(uri, fromCache){
            var status = true;
            //need to draw every time since an expanded tree won't update with just bound data update
            var treeViewContainer =  this.element.querySelector(".treeViewContainer");
            //first clean up treeViewContainer
            while(treeViewContainer.hasChilden){
                treeViewContainer.removeChild(treeViewContainer.lastChild);
            }
            //now draw the unexpanded tree with the current uri data

            if(!!treeViewContainer){
                var data = [];
                if((typeof fromCache === 'undefined') || (fromCache === true)){
                    data = this.application.ninja.filePickerController.prepareContentList(uri, this.pickerModel);
                }
                else{
                    data = this.application.ninja.filePickerController.prepareContentList(uri, this.pickerModel, false);
                }

                if(data.length > 0){

                    //clear selection
                    this.clearSelection();
                    this.spanEl = this.element.querySelector(".treeViewContainer").querySelector(".noResults");
                    if(!!this.spanEl){
                        this.spanEl.style.display = "none";
                    }

                    var tree = treeModule.Tree.create();
                    tree.treeViewDataObject = data;
                    tree.element = treeViewContainer;
                    tree.needsDraw = true;

                }else{

                    var treeUl = treeViewContainer.getElementsByTagName("ul")[0];
                    if(!!treeUl){
                        treeUl.style.display = "none";
                    }

                    this.spanEl = this.element.querySelector(".treeViewContainer").querySelector(".noResults");
                    if(!!this.spanEl){
                        this.spanEl.style.display = "block";
                    }else{
                        this.spanEl = document.createElement("span");
                        this.spanEl.className = "noResults";
                        this.spanEl.innerHTML = "no results";
                        this.spanEl.style.display = "block";
                        this.element.querySelector(".treeViewContainer").appendChild(this.spanEl);
                    }

                    status = false; //for no match
                }

                this.updateMetadata(uri);

                return status;
            }
        }
    },

    updateMetadata:{
        enumerable: false,
        writable:false,
        value:function(currentUri){
            var data = this.application.ninja.filePickerController._directoryContentCache[currentUri];
            var metadata = "";
            if(!!data){
                if(data.name !== ""){
                    metadata = "Name: "+data.name;
                }
                metadata = metadata + "<br />" + "Type: "+data.type;
                if(data.size){metadata = metadata + "<br />" + "Size: "+data.size+" bytes";}
                if(data.creationDate){metadata = metadata + "<br />" + "Creation date: "+ this.formatTimestamp(data.creationDate);}
                if(data.modifiedDate){metadata = metadata + "<br />" + "Modified date: "+ this.formatTimestamp(data.modifiedDate);}
            }
            this.element.getElementsByClassName("right-bottom")[0].innerHTML = metadata;
        }
    },

    isOutside:{
        enumerable:true,
        value:function(el, targetEl){
            var isOutside = true;
            if(el){
                var childElements = el.getElementsByTagName("*");//get a flat NodeList of all the child elements
                if(childElements != null){
                    for(var i=0; i< childElements.length; i++){
                        if(childElements[i] === targetEl){//targetEl matches with an element inside the menu
                            isOutside = false;
                            break;
                        }
                    }
                }
            }
            return isOutside;
        }
    },
    /**
     * convert timestamp to human readable form
     *
     * @param: timestamp - UTC milliseconds
     */
    formatTimestamp:{
        writable:false,
        enumerable: false,
        value: function(timestamp) {
            var aDate = new Date();
            timestamp = timestamp - (aDate.getTimezoneOffset()*60*1000);//convert from GMT to local timestamp
            aDate = new Date(timestamp);
            return aDate.toLocaleString();
        }
    },

    /**
     * Event Listners
     */

    addIdentifiers:{
        value: function(){
            this.element.identifier = "pickerNav";
            //this.addressGo.identifier = "addressGo";
            this.addressBarUri.identifier = "addressBarUri";
            this.refreshButton.identifier = "refreshButton";
            this.backArrow.identifier = "backArrow";
            this.forwardArrow.identifier = "forwardArrow";
            this.iconView.identifier = "iconView";
            this.treeView.identifier = "treeView";
            this.resultsArea.identifier = "resultsArea";
        }
    },

    handleTopLevelDirectoryClicks : {
        enumerable: true,
        writable: false,
        value : function(evt, dirObj){
                    this.currentURI = this.pickerModel.currentLogicalDrive = dirObj.uri;

                    var status = this.pickerViews()[this.selectedPickerView].call(this, dirObj.uri);//dynamically calls the update function of the current picker view

                    this.updateAddressBar(dirObj.uri);
                    this.pickerModel.currentRoot = dirObj.uri;

                    //populate history
                    this.pickerModel.storeHistory(dirObj.uri);
                    //disable forward button for explicit new urls
                    if(!this.forwardArrow.classList.contains("disable")){
                        this.forwardArrow.classList.add("disable");
                    }
                    //enable back button if required
                    if((this.pickerModel.currentHistoryPointer === 1) && this.backArrow.classList.contains("disable")){
                        this.backArrow.classList.remove("disable");
                    }

                    //dehighlight current selection and highlight new selection
                    var currentHighlighted = evt.target.parentNode.querySelector(".highlighted");
                    if(!!currentHighlighted){
                        currentHighlighted.classList.remove("highlighted");
                    }
                    if(!evt.target.classList.contains("highlighted")){
                        evt.target.classList.add("highlighted");
                    }

                    //enable ok for logical drive selections, when in directory selection mode
                    if(this.pickerModel.inFileMode === false){
                        this.okButton.removeAttribute("disabled");
                        //put into selectedItems..currently single selection is supported
                        this.selectedItems = [dirObj.uri];
                    }
                }
    },

    handlePickerNavOpenFolder: {
        value: function(evt){
                    this.currentURI = evt.folderUri;
                    var status = this.pickerViews()[this.selectedPickerView].call(this, evt.folderUri);//dynamically calls the update function of the current picker view

                    //update address-bar
                    this.updateAddressBar(evt.folderUri);

                    //populate history
                    this.pickerModel.storeHistory(evt.folderUri);

                    //disable forward button for explicit new urls
                    if(!this.forwardArrow.classList.contains("disable")){
                        this.forwardArrow.classList.add("disable");
                    }

                    //enable back button if required
                    if((this.pickerModel.currentHistoryPointer === 1) && this.backArrow.classList.contains("disable")){
                        this.backArrow.classList.remove("disable");
                    }

                    //for directory selection, selected url is the folder entered
                    if(!this.pickerModel.inFileMode ){
                        this.okButton.removeAttribute("disabled");
                        //put into selectedItems..currently single selection is supported
                        this.selectedItems = [evt.folderUri];
                    }

                }
    },


    handlePickerNavSelectedItem: {
        value:function(evt){
                    var uri = evt.uri;

                    //handle deselection of other icons for single selection
                    if((this.currentSelectedNode !== null) && (this.currentSelectedNode !== evt.target) && (this.currentSelectedNode.classList.contains("selected"))){
                        this.currentSelectedNode.classList.remove("selected");
                        this.currentSelectedNode = null;
                    }
                    //enable OK button if the selection is valid as per the picker mode
                    if((this.pickerModel.inFileMode && (this.application.ninja.filePickerController._directoryContentCache[uri].type === "file"))
                        || (!this.pickerModel.inFileMode && (this.application.ninja.filePickerController._directoryContentCache[uri].type === "directory"))){
                        this.okButton.removeAttribute("disabled");

                        //put into selectedItems..currently single selection is supported
                        this.selectedItems = [uri];

                        if(!evt.target.classList.contains("selected")){
                            evt.target.classList.add("selected");
                        }

                        this.currentSelectedNode = evt.target;

                    }else{


                        //test: highlight non-selectable icons too
                        if(!evt.target.classList.contains("selected")){
                            evt.target.classList.add("selected");
                        }
                        this.currentSelectedNode = evt.target;
                        //end- test


                        //disable OK
                        if(!this.okButton.hasAttribute("disabled")){
                            this.okButton.setAttribute("disabled", "true");
                        }
                    }
            }
    },

    handlePickerNavSelectedFile:{
        value: function(evt){
            var uri = evt.fileUri;

            //do selection if in file selection mode
            if(this.pickerModel.inFileMode && (this.application.ninja.filePickerController._directoryContentCache[uri].type === "file")){
                this.okButton.removeAttribute("disabled");
                //put into selectedItems..currently single selection is supported
                this.selectedItems = [uri];
                this.currentURI = uri.substring(0, uri.lastIndexOf("/"));
                this.handleOkButtonAction();
            }
        }
    },

    handlePickerNavShowMetadata: {
        value: function(evt){
                //update matadata only if nothing is already selected
                if(this.currentSelectedNode == null){
                    //console.log("handle showmetadata - true");
                    this.metadataSection.innerHTML = evt.metadata;
                }
        }
    },

    handlePickerNavUpdateMetadata:{
        value: function(evt){
                    this.metadataSection.innerHTML = evt.metadata;
                }
    },

    handleAddressGoClick :{
        value: function(evt){

                    if(this.addressBarUri.value !== ""){
                        var uri = this.addressBarUri.value;
                        uri = this.cleanupUri(uri);

                        this.currentURI = uri;
                        var status = this.pickerViews()[this.selectedPickerView].call(this, uri);//dynamically calls the update function of the current picker view

                        //populate history
                        this.pickerModel.storeHistory(uri);

                        //disable forward button for explicit new urls
                        if(!this.forwardArrow.classList.contains("disable")){
                            this.forwardArrow.classList.add("disable");
                        }

                        //enable back button if required
                        if((this.pickerModel.currentHistoryPointer === 1) && this.backArrow.classList.contains("disable")){
                            this.backArrow.classList.remove("disable");
                        }
                    }
                }
    },

    handleAddressBarUriKeydown:{
        value: function(evt){
                    if(evt.keyCode === 13 ){
                        var uri = this.addressBarUri.value;
                        uri = this.cleanupUri(uri);

                        this.currentURI = uri;

                        var status = this.pickerViews()[this.selectedPickerView].call(this, uri);//dynamically calls the update function of the current picker view

                        //populate history
                        this.pickerModel.storeHistory(uri);
                        //disable forward button for explicit new urls
                        if(!this.forwardArrow.classList.contains("disable")){
                            this.forwardArrow.classList.add("disable");
                        }
                        //enable back button if required
                        if((this.pickerModel.currentHistoryPointer === 1) && this.backArrow.classList.contains("disable")){
                            this.backArrow.classList.remove("disable");
                        }
                    }
              }
    },

    handleAddressBarUriKeyup:{
        value: function(evt){
            //disable ok if user enters an invalid uri
            if(!this.application.ninja.coreIoApi.isValidUri(this.addressBarUri.value)){
                //disable OK
                if(!this.okButton.hasAttribute("disabled")){
                    this.okButton.setAttribute("disabled", "true");
                }
            }else{
                this.okButton.removeAttribute("disabled");
                this.selectedItems = [this.addressBarUri.value];
            }
        }
    },

    handleRefreshButtonClick:{
        value:function(evt){
                var uri = this.addressBarUri.value;
                uri = this.cleanupUri(uri);

                var status = this.pickerViews()[this.selectedPickerView].call(this, uri, false);//dynamically calls the update function of the current picker view

            }
    },

    handleBackArrowClick :{
        value:function(evt){
                var uri = "";
                //console.log("*** backArrow: pointer ="+this.pickerModel.currentHistoryPointer);
                if(this.pickerModel.currentHistoryPointer >0){
                    uri = this.pickerModel._history[this.pickerModel.currentHistoryPointer -1];
                    //console.log("*** back uri= "+ uri);
                    //console.log(this.pickerModel._history);

                    this.currentURI = uri;
                    var status = this.pickerViews()[this.selectedPickerView].call(this, uri);//dynamically calls the update function of the current picker view

                    //update address-bar
                    this.updateAddressBar(uri);

                    this.pickerModel.currentHistoryPointer -= 1;

                    //disable back button if it is at the beginning
                    if((this.pickerModel.currentHistoryPointer === 0) && (!evt.target.classList.contains("disable"))){
                        evt.target.classList.add("disable");
                    }
                    //enable forward button if required
                    if((this.pickerModel.currentHistoryPointer < (this.pickerModel._history.length -1) && (this.forwardArrow.classList.contains("disable")))){
                        this.forwardArrow.classList.remove("disable");
                    }
                }
                //console.log("***new backArrow: pointer ="+this.pickerModel.currentHistoryPointer);
            }
    },

    handleForwardArrowClick: {
        value:function(evt){
                var uri = "";
                //console.log("*** forwardArrow: pointer ="+this.pickerModel.currentHistoryPointer);
                if(this.pickerModel.currentHistoryPointer < (this.pickerModel._history.length -1)){
                    uri = this.pickerModel._history[this.pickerModel.currentHistoryPointer + 1];
                    //console.log("*** forward uri= "+ uri);
                    //console.log(this.pickerModel._history);

                    this.currentURI = uri;
                    var status = this.pickerViews()[this.selectedPickerView].call(this, uri);//dynamically calls the update function of the current picker view

                    //update address-bar
                    this.updateAddressBar(uri);

                    this.pickerModel.currentHistoryPointer += 1;

                    //disable forward button if pointer is at the end
                    if((this.pickerModel.currentHistoryPointer === (this.pickerModel._history.length -1)) && (!evt.target.classList.contains("disable"))){
                        evt.target.classList.add("disable");
                    }

                    //enable back button if required
                    if((this.pickerModel.currentHistoryPointer > 0) && (this.backArrow.classList.contains("disable"))){
                        this.backArrow.classList.remove("disable");
                    }

                }
                //console.log("***new forwardArrow: pointer ="+this.pickerModel.currentHistoryPointer);
            }
    },

    handleOkButtonAction : {
        value: function(evt){
                    //console.log("$$$ File Picker : selected "+ this.selectedItems.toString());
                    var success = true;
                    if(!!this.pickerModel.callback && (this.selectedItems.length > 0)){//call the callback if it is available
                        try{
                            this.pickerModel.callback({"uri":this.selectedItems});
                        }catch(e){
                            success = false;
                            console.log("[Error] Failed to open "+ this.selectedItems.toString());
                            console.log(e.stack);
                        }
                    }else{//else send an event with the selected files
                        var pickerSelectionEvent = document.createEvent("Events");
                        pickerSelectionEvent.initEvent("pickerSelectionsDone", false, false);
                        pickerSelectionEvent.selectedItems = this.selectedItems;
                        this.eventManager.dispatchEvent(pickerSelectionEvent);
                    }

                    //store last opened/saved folder, and view after IO is successful
                    var dataStore = window.sessionStorage;
                    try {
                        if(this.pickerModel.pickerMode === "write"){
                            dataStore.setItem('lastSavedFolderURI', encodeURI(""+this.currentURI));
                        }
                        else if(this.pickerModel.inFileMode === true){
                            dataStore.setItem('lastOpenedFolderURI_fileSelection',encodeURI(""+this.currentURI));
                        }else if(this.pickerModel.inFileMode === false){
                            dataStore.setItem('lastOpenedFolderURI_folderSelection',encodeURI(""+this.currentURI));
                        }
                    }
                    catch(e){
                        if(e.code == 22){
                            dataStore.clear();
                        }
                    }

                    this.cleanup();//clear up any unnecessary memory

                    if(this.popup){
                        this.popup.hide();
                    }
                    //end - close dialog
              }
    },

    handleCancelButtonAction :{
        value:function(evt){
                //clean up memory
                this.cleanup();

                if(this.popup){
                    this.popup.hide();
                }

            }
    },

    handleFilterClick:{
        value: function(evt, aFilter, filtersDD){
                    this.pickerModel.currentFilter = aFilter;

                    this.pickerViews()[this.selectedPickerView].call(this, this.currentURI);//dynamically calls the update function of the current picker view

                    this.element.querySelector(".filters .filterVal").innerHTML = evt.target.innerHTML;
                    filtersDD.classList.toggle("hide");
                }
    },

    handleAddressDropdownArrowClick:{
        value: function(evt){
            var that = this;

            //populate dropdown dynamically for addressbar
            var addressbarDD = this.element.querySelector(".addressbar .dropdown");
            if((evt.target === this.element.querySelector(".addressbar .dropdownArrow")) && (addressbarDD.classList.contains("hide"))){//dropdown is closed

                //clear old dropdown contents
                while(addressbarDD.hasChildNodes()){
                    addressbarDD.removeChild(addressbarDD.lastChild);
                }

                var uriTrail = this.prepareAddressDropdownData(this.addressBarUri.value);
                if(uriTrail.length >0){
                    uriTrail.forEach(function(aUri){
                        var newDiv = document.createElement("div");
                        newDiv.innerHTML = aUri;
                        addressbarDD.appendChild(newDiv);
                        newDiv.addEventListener("click", function(evt){that.handleAddressTrailClick(evt, aUri, addressbarDD);}, false);
                    }, this);
                }
            }
            //open close dropdown
            this.toggleDropdown(evt.target);
        }
    },

    handleAddressTrailClick: {
        value: function(evt, aUri, addressbarDD){
                    this.currentURI = aUri;
                    var status = this.pickerViews()[this.selectedPickerView].call(this, aUri);//dynamically calls the update function of the current picker view

                    //populate history
                    this.pickerModel.storeHistory(aUri);
                    //disable forward button for explicit new urls
                    if(!this.forwardArrow.classList.contains("disable")){
                        this.forwardArrow.classList.add("disable");
                    }
                    //enable back button if required
                    if((this.pickerModel.currentHistoryPointer === 1) && this.backArrow.classList.contains("disable")){
                        this.backArrow.classList.remove("disable");
                    }
                    this.addressBarUri.value = evt.target.innerHTML;
                    addressbarDD.classList.toggle("hide");
                }
    },

    handleIconViewClick :{
        value:function(evt){

                this.selectedPickerView = "iconView";

                if(this.element.querySelector(".iconViewContainer").style.display === "none"){
                    //draw if icons list is not already drawn
                    if(this.iconsViewDrawnOnce === false){
                        this.iconList = iconsListModule.IconsList.create();
                        this.iconList.iconsViewDataObject = that.mainContentData;
                        this.iconList.element = that.iconViewContainer;
                        this.iconList.needsDraw = true;
                        this.iconsViewDrawnOnce = true;
                    }else{
                        this.pickerViews()[this.selectedPickerView].call(this, this.currentURI);
                    }
                    this.element.querySelector(".iconViewContainer").style.display = "block";
                }
                this.element.querySelector(".treeViewContainer").style.display = "none";

                //enable selection
                if(!evt.target.classList.contains("viewSelected")){
                    evt.target.classList.add("viewSelected")
                }
                if(this.treeView.classList.contains("viewSelected")){
                    this.treeView.classList.remove("viewSelected");
                }
            }
    },

    handleTreeViewClick : {
        value:function(evt){

                this.selectedPickerView = "treeView";

                if(this.element.querySelector(".treeViewContainer").style.display === "none"){

                    this.pickerViews()[this.selectedPickerView].call(this, this.currentURI);

                    this.element.querySelector(".treeViewContainer").style.display = "block";
                }
                this.element.querySelector(".iconViewContainer").style.display = "none";

                //enable selection
                if(!evt.target.classList.contains("viewSelected")){
                    evt.target.classList.add("viewSelected")
                }
                if(this.iconView.classList.contains("viewSelected")){
                    this.iconView.classList.remove("viewSelected");
                }

            }
    },

    handlePickerNavDrawTree:{
        value: function(evt){
                //toggle open or close for directory
                if(evt.uriType === "directory"){
                    this.renderTree(evt.subTreeContainer, evt.uri);
                }
            }
    },

    handlePickerNavRefreshTreeSegment:{
        value: function(evt){
//                if(this.application.ninja.filePickerController.checkIfStale(evt.uri)){
//                    //update tree segment if was stale
//                    evt.treeSegment.treeViewDataObject = this.application.ninja.filePickerController.prepareContentList(evt.uri, this.pickerModel, true, false);
//                }
            }
    },

    handleResultsAreaClick: {
        value:function(evt){
                //console.log("### clicked right-top");
                if((evt.target.querySelectorAll(".icon").length > 1)
                    || (evt.target.querySelectorAll(".atreeItem").length > 1)){//not clicked on an icon
                    //console.log("@@ clicked in empty area");
                    this.clearSelection();
                }
            }
    },

    handlePickerNavClick:{
        value: function(evt){
                //console.log("### clicked picker");
                this.closeDropdowns(evt.target);
            }
    },

    getComputedWidth:{
        value: function(element){
            var calculatedWidth = "0px";
            var orginalDisplay = element.style.display;
            var originalVisibility = element.style.visibility;
            element.style.display = "block";
            element.style.visibility = "hidden";
            calculatedWidth = window.getComputedStyle(element, null).getPropertyValue("width");
            element.style.display = orginalDisplay;
            element.style.visibility = originalVisibility;
            return calculatedWidth;
        }
    },

    cleanup:{
            writable:false,
            enumerable:true,
            value:function(){
                //clear memory - TODO:check for more memory leaks
                this.pickerModel = null;
                this.application.ninja.filePickerController._directoryContentCache = {};
                this.application.ninja.filePickerController.pickerNavChoices = null;
                //remove listeners
                this.element.removeEventListener("openFolder", this, false);//add icon double click event listener to reload iconList with new set of data
                this.element.removeEventListener("selectedItem", this, false);//for single selection only
                this.element.removeEventListener("showMetadata", this, false);//show metadata on hover of icon
                this.element.removeEventListener("updateMetadata", this, false);//show metadata on click of icon
                //this.addressGo.removeEventListener("click", this, false);
                this.addressBarUri.removeEventListener("keydown", this, false);
                this.refreshButton.removeEventListener("click", this, false);//refresh - gets from file system directly
                this.backArrow.removeEventListener("click", this, false);
                this.forwardArrow.removeEventListener("click", this, false);
                this.iconView.removeEventListener("click", this, false);
                this.treeView.removeEventListener("click", this, false);
                this.element.removeEventListener("drawTree", this, false);
                this.resultsArea.removeEventListener("click", this, false);
                this.element.removeEventListener("click", this, false);

            }
        }

});