var zoo = {};
zoo.version = "0.0.1";

zoo.dom = {

    popUp: function(aURL, aWidth, aHeight, aScroll) {
        var zLeft = (screen.width - aWidth) / 2;
        var zTop = (screen.height - aHeight) / 2;
        var zWinProp = 'width='+aWidth+',height='+aHeight
                     + ',left='+zLeft+',top='+zTop+',scrollbars='+aScroll+',resizable';
        zWin = window.open(aURL, '', zWinProp);
        zWin.window.focus();
    },
    
    widgets: {
        ValuePrompt: function() {           
            var display = function(event) {
                var element = event.element(event);
                if (!element.value) {
                    element.addClassName('prompt');
                    element.value = '[' + element.getAttribute('prompt') + ']';
                }
            }
            
            var remove = function(event) {
                var element = event.element(event);
                var prompt = '[' + element.getAttribute('prompt') + ']';
                if (element.value == prompt) {
                    element.removeClassName('prompt');
                    element.value = '';
                }
            }
            
            return function() {
                $$('input[prompt]').each(function(input) {
                    input.observe('focus', remove);
                    input.observe('blur', display);
                    display({
                        element: function() {
                            return input;
                        }
                    });
                });
            }
        }(),
        
        Hoverable: function() {
            // elementype = elementype || 'tr';
            var elements = this.elements = $$('*[hoverable="Y"]');         
            var l = elements.length;
                       
            for (var i = 0; i < l ; i++) {
                var $elm = elements[i];
                
                $elm.observe('mouseover', function() {
                    this.addClassName('hover');
                });
                   
                $elm.observe('mouseout', function() {
                    this.removeClassName('hover');
                });
                
            }
            return true;
        },
        
        Table: function() {
            $$('a.ico-remove').each(function(link) {
                // console.info(link);
                link.observe('click', zoo.remove);
            })
            return true;
        }
    }
    
}

zoo.user = {
  
    save: function() {       
        var email   = $('inp-password');
        var confirm = $('inp-confirm-password');
        
        // console.log(email.value + ' ' + confirm.value);
        
        if (email.value == confirm.value) {
            
            alert('ok');
            return false;
            return zoo.form.save();
        }
        console.log("password not confirmed!");
        return false;
    },
  
    widgets: {
        
        passwordUpdate: function() {
            
            var inpEmail = {}, inpConfirm = {}
            
            var init = function() {
                inpEmail.value = this.value;
                var confirm = inpConfirm.elm;
                confirm.removeClassName('disabled');
                confirm.disabled = false;                
                return true;
            }
            
            var update = function() {
/*                
                var confirm = inpConfirm.elm;                
                confirm.addClassName('disabled');
                confirm.disabled = true;                  
                return true;
*/
            }
            
            var enable = function() {
                
            }
            
            var confirm = function() {
                                
                
            }            
            
            return function() {
                var email   = $('inp-password');
                var confirm = $('inp-confirm-password');
                
                email.observe('focus', init);
                confirm.observe('blur', update);
                
                inpEmail.elm   = email;
                inpConfirm.elm = confirm;
                return true;
                
            }
            
        }()  
    
    }
    
}

zoo.form = function() {
        
    var _displayError = function(form, emptyfields) {
        var errorNode = form.errorMsg || $(form.getAttribute('name') + '-err');
        if (!errorNode) {
            var errorNode = new Element('div', {className: 'form-err', id: form.getAttribute('name') + '-err' });
            form.errorMsg = errorNode;
        }
        errorNode.update();
        errorNode.insert(
            new Element('h3').update('Sorry your form had a few problems')
        );
        errorNode.insert(new Element('p').update('Please re-enter the fields in red:'));

        var errorList = new Element('ul');            

        emptyfields.each(function(field) {
            var parentEl = $(field.parentNode);
            var label = parentEl.select('label')[0];            
            // check if field has its own error label
            if (field.getAttribute('errorName')) {
                var errorLabel = field.getAttribute('errorName');
            } else {
                var errorLabel = label.innerHTML.replace(':', '');
            }

            label.addClassName('error');
    
            var errorReason = field.invalidElement ? ' : <span class="error">' + field.invalidElement : '</span>';
            errorList.insert(new Element('li').update(
                errorLabel + errorReason
            ));
        });

        errorNode.insert(errorList);

        form.parentNode.insertBefore(errorNode, form);

        if (window.Modalbox) {
            Modalbox.MBcontent.scrollTop = 0;
        } else {
            errorNode.scrollTo();
        }

        if (window.Modalbox) {
            zoo.Modalbox.resizeToContent();
        }
        // if(window.Modalbox) Modalbox.MBwindow.shake(
        errorNode.highlight();
        return true;
    }
    var _validateForm = function(form) {
        form = $(form);
        var inputs = form.getElements();
        // var inputs = form.getInputs();
        var emptyFields = [];
        var invalidFields = [];
        var validateType, rte;
        
        inputs.each(function(field) {
            // reset label if previously errored on.
            field = $(field);
            if (field.error) {
                var parentEl = $(field.parentNode);
                var label = parentEl.select('label')[0];
                if (label) label.removeClassName('error');
                field.error = null;
                if (field.invalidElement) field.invalidElement = null;
            }
            // check if required
            if (field.getAttribute('required') == "Y" && !field.getValue()) {
                field.error = true;
                emptyFields.push(field);
                return;
            }
            
            // check if we need to validate
            var validateType = field.getAttribute('validate')
            if (validateType) {
                // check if validate type has params embedded in it
                var validRegEx = /\[.*/;
                var match = validateType.match(validRegEx);
                var validateParam = '';
                // if it does, then strip them out and pass to validator                
                if (match) {
                    validateType = validateType.replace(validRegEx, '');
                    validateParam = match[0].replace(/^\[|\]$/g, '');
                }                
                var validResult = _validationHandler[validateType](field, form, validateParam);
                if (validResult.error) {
                    field.error = true;
                    field.invalidElement = validResult.error;
                    invalidFields.push(field);             
                }
                return;
            }
            isRTE = field.getAttribute('rte');           
            if (isRTE) {
                var rte = tinyMCE.get(field.id);
                field.value = rte.getContent();
            }
        })
               
        return {
            emptyFields   : emptyFields,
            invalidFields : invalidFields               
        }       

    }
    
    var _validationHandler = function() {
        
        return {
            
            email: function(field) {
                var str = field.getValue();
                var error="";
         
                var emailFilter=/^.+@.+\..{2,3}$/;
                if (!(emailFilter.test(str))) {
                    return {
                        error: "Please enter a valid email address.\n"
                    }
                    return false;
                }
                else {
                    //test email for illegal characters
                    var illegalChars= /[\(\)\<\>\,\;\:\\\"\[\]]/
                    if (str.match(illegalChars)) {

                        return {
                            error: "The email address contains illegal characters.\n"
                        }
                   }
                }
                return {
                    error: false    
                }
            },
            
            /**
             * checks for valid password
             * @todo check for reason of error
             */
            password: function(field) {
                var str = field.getValue();
                
                var illegalChars = /[\W_]/; // allow only letters and numbers
                // if ((str.length < 6) || (str.length > 10)){
                if (str.length < 6){
                    return {
                        error: "Must be greater than 6 characters.\n"
                    }
                }
                else if (illegalChars.test(str)) {
                    return {
                        error: "Contains illegal characters.\n"
                    }
                }
                
                else if (!((str.search(/[a-z]+/) > -1)
                    && (str.search(/[A-Z]+/) > -1)
                    && (str.search(/[0-9]+/) > -1))) {
                    return {
                        error: "Must contain at least one uppercase letter, one lowercase letter, and one numeral.\n"
                    }
                    return false;
                }
                return true;
            },
            
            confirmPassword: function(field, form, checkAgainstFieldName) {
                if (!form[checkAgainstFieldName]) throw new Error('confirm password does not have a valid password field to check against! - ' + checkAgainstFieldName);
                if (field.getValue() !== form[checkAgainstFieldName].getValue()) {
                    // reset field
                    field.value = '';
                    return {
                        error: 'does not match password'
                    }
                }
                return {
                    error: false
                }
                
            return false;                
            },
            
            username: function(field) {
                var str = field.getValue();
                var illegalChars = /\W/; // allow letters, numbers, and underscores
                if ((str.length < 4) || (str.length > 10)) {
                    return {
                        error: "The username is the wrong length.\n"
                    }
                }
                else if (illegalChars.test(strng)) {
                    return {
                        error: "The username contains illegal characters.\n"
                    }
                } 
                return false;   
            },
            
            number: function(field, digits) {
                var number = field.getValue();
                
                if(isNaN(number)) {
                    return {
                        error: "Must only contain numbers."
                    }
                }
                /*
                if (digits && number.length > digits) {
                    return {
                        error: "Must contain only " + digits + " dgits."
                    }                    
                }
                */
                return false;   
            }
            
        }
        
    }();
    
    
    return {
        
        init: function() {
            
            
        },
        
        loading: function(form) {
            if (window.Modalbox) {
                form.style.display = "none";
                Modalbox.MBcontent.insert(new Element('p', {className: 'form-save-msg'}).update('Saving, please be patient...'));
                Modalbox.MBcontent.insert(Modalbox.MBloading);

                // Modalbox.MBcontent.update(new Element('p', {className: 'form-save-msg'}).update('Saving, please be patient...'));
                // Modalbox.MBcontent.appendChild(Modalbox.MBloading);
                Modalbox.resizeToContent();
            }
            return true;
        },
        
        success: function(transport) {
            if (window.Modalbox) {
                // Modalbox.show("<p>Form Has Been Saved Successfully</p>");
                // Modalbox.resizeToContent();
                Modalbox.hide(); 
            }
            setTimeout(function() {
               location.reload(true);
            }, 500);
            return true;
        },
       
        save: function(form) {
            
            // wrap save in try catch so that we never submit bad form
            try {
                var results = _validateForm(form);
     
                /* remove shaking of modalbox... for now. */
                var errorFields = [];
                errorFields = errorFields.concat(results.emptyFields, results.invalidFields);
                
                if (errorFields.length) {
                    _displayError(form, errorFields);
                    return false;
                }
                // useful when we need to debug
                // return true;   
                // check if we hijack form save and use ajax
                if (window.Modalbox || form.getAttribute("ajax") == "Y") {
                    this.loading(form);
                    if (form.getAttribute("enctype")) {
                        form.hasFiles = true;
                        // if we have a file post to an iframe and do not use
                        // ajax method
                        AIM.submit(form, {
                            'onStart'   : Prototype.emptyFunction,
                            'onComplete': this.success
                        });
                        return true;
                    }
                    var url = form.action;
                    new Ajax.Request(url, {
                        method: 'post',
                        parameters: form.serialize(true),   
                        // onSuccess: Prototype.emptyFunction
                        onSuccess: this.success
                    });
                    return false;
                }
                
                return true;

            } catch(e) {
                // @todo need sys email here
                if (window.console) {
                    console.dir(e);
                }
                return false;
            }           
        },
        
        /* date input class */
        Date: function(element) {
            this.ico    = element;
            var dateId  = element.getAttribute('date-id');
            this.input  = $(dateId);
            zoo.form.Date.instances[dateId] = this;
            zoo.form.Date.instanceArray.push(this);
        }
      
    }
  
}();

/* ########################################################################## */
/*   date formfield widget                                                    */
/* ########################################################################## */
zoo.form.Date.instanceArray = [];
zoo.form.Date.instances = {};
zoo.form.Date.show = function(el) {
    
    var scalCalendar = $('scal-calendar');
    if (!scalCalendar) {

        scalCalendar = new Element('div', {
            className: 'scal tinyscal zscal',
            id: 'scal-calendar'
        });
        var modalBox = $('XXXXMB_window');
        if (modalBox) {
            modalBox.appendChild(scalCalendar);
            
        } else {
            
            document.body.insertBefore(scalCalendar, document.body.firstChild);    
        }
        
    }
    
    // get id of date input
    var dateId = el.getAttribute('date-id');
    // do we have a js instance of this?
    var dateInput = zoo.form.Date.instances[dateId];
    // if no, create one first
    if (!dateInput) {
        dateInput = new zoo.form.Date(el);
    }
    dateInput.calElement = scalCalendar;
    // display calendar
    dateInput.show();
    return true;
}

zoo.form.Date.prototype = {
    
    show: function() {
        if (!this.scal) {
            var self = this;
            this.scal = new scal('scal-calendar', this.update, {
                updateformat: 'mm/dd/yyyy',
                closebutton: '<img src="/img/close-ico.jpg" />'              
            });
            this.scal.zooDate = this;
            
            var onSelChange = function(){
                var updateElement = self.zooDate.input;
                updateElement[updateElement.tagName == 'INPUT' ? 'setValue' : 'update'](this.currentdate.format(this.options.updateformat));
                self.scal.closeCalendar();
            };
            this.input.observe('keypress', this.hide.bindAsEventListener(this));            
        } else {
            this.scal.zooDate.open = false;
        }
        var date = new Date($F(this.input));
        this.scal.setCurrentDate(isNaN(date) ? new Date() : date);
        var dim = this.ico.cumulativeOffset()     
        this.calElement.style.top  = dim.top + 'px';
        this.calElement.style.left = dim.left + 30 + 'px';
        this.calElement.style.display = "block";       
    },
    
    hide: function() {
        if(this.scal.isOpen()) {
            this.scal.closeCalendar();
            this.open = false;
        }
        return true;        
    },
    
    update: function() {
        this.zooDate.input.value = this.currentdate.format('mm/dd/yyyy');
        if (this.zooDate.opened) {
            this.closeCalendar();
            this.zooDate.opened = false;
        } else {
            this.zooDate.opened = true;
        }
        return true;
    }
}

/* ########################################################################## */
/*   multi entry formfield widget                                             */
/* ########################################################################## */
zoo.form.MultiEntry = function(entryId, fields) {
    this.multiEntryContainer = $(entryId);

    this.addButton = this.multiEntryContainer.select('button.btn-entry')[0];

    this.id = 'multi-entry-' + Math.floor(Math.random() * 99999);
    this.addButton.setAttribute('multi-entry-id', this.id);
    this._fields = fields;
    zoo.form.MultiEntry.instance[this.id]= this;
}
zoo.form.MultiEntry.prototype = function() { 
    var _getEntryInputs = function() {
        this.addContainer = $(this.addButton.parentNode);
        this.entryFields = this.addContainer.select('.text, select');
    }
    
    var _getValueContaines = function() {
        var formFieldContainer = $(this.addContainer.parentNode);
        this.entryTable    = formFieldContainer.select('table.multi-entry')[0];
        this.hiddenEntries = formFieldContainer.select('div.hidden-entries')[0];
    }
    
    var _getValues = function() {
        var values = {};
        this.entryFields.each(function(input) {
            var field = input.getAttribute('name').replace('-entry', '');
            var display = input.tagName == 'SELECT' ? input.options[input.selectedIndex].text : input.getValue();
            values[field] = { value: input.getValue(), display: display };
            input.value = '';
        });
        return values;
    }
    
    var _addValuesToHiddenInputs = function(values) {
        var inputElement;
        for (field in values) {
            inputElement = new Element('textarea', {
                'class': 'hidden',
                name: field + '[]',
                value: values[field].value
            }).update(values[field].value);
            // ie no likey this.. class hidden hides it for us
            // inputElement.setAttribute('type', 'hidden');
            this.hiddenEntries.appendChild(inputElement);
        }
        return true;
    }
    
    var _getTBody = function() {
        if (this.entryTBody) return this.entryTBody;
        var els  = this.entryTable.select('tbody');
        if (els) {
            var tBody = els[0];
        } else {
            var tBody = document.createElement();
            this.entryTable.appendChild(tBody);
        }
        this.entryTBody = tBody;
        return tBody;            
    }
    
    var _addValuesToEntryTable = function(values) {
        var tBody = _getTBody.call(this);
        var cell;
        var row = new Element('tr');

        var items = tBody.select('cell');
  
        var className = items.length % 2 == 0 ? 'even' : 'odd';
        row.addClassName(className);
        
        row.observe('mouseover', function() {
            this.addClassName('hover');
        });
           
        row.observe('mouseout', function() {
            this.removeClassName('hover');
        });

        for (field in this._fields) {
            if (!values[field]) continue;
            cell = new Element('td', { 'class': 'item-' + field }).update(values[field].display);
            row.appendChild(cell);
        }
                    
        var removeLink = new Element('a', {
            'class': 'button-anchor remove'
        }).update('remove')

        removeLink.observe('click', this.removeEntry.bindAsEventListener(this, row));
                         
        cell = new Element('td', { 'class': 'item-remove' }).update(removeLink);

        row.appendChild(cell);

        tBody.appendChild(row);
        
        return true;
    }
    
    var _updateRemoveLinks = function() {
        var self = this;
        this.multiEntryContainer.select('table.multi-entry a.remove').each(function(removeLink) {
            var row = removeLink.parentNode.parentNode;
            removeLink.observe('click', self.removeEntry.bindAsEventListener(self, row));
        })            
    }
    
    return {
        init: function() {
            _getEntryInputs.call(this);
            _getValueContaines.call(this);
            _updateRemoveLinks.call(this);
        },
        add: function(values) {
            _addValuesToHiddenInputs.call(this, values);
            _addValuesToEntryTable.call(this, values);
        },
        addEntry: function() {
            var values = _getValues.call(this);
            this.add(values);
            return true;
        },
        removeEntry: function(e, row) {
            var tBody = _getTBody.call(this);
            var valueRows = tBody.select('tr');
            var killRow   = valueRows.indexOf(row);
            var hiddenFields;
            for (field in this._fields) {              
                hiddenFields = this.hiddenEntries.select('textarea[name="' + field + '[]"]');
                if (hiddenFields[killRow]) {
                    this.hiddenEntries.removeChild(hiddenFields[killRow]);
                }
            }
            row.parentNode.removeChild(row);
        },
        getId: function() {
            return this.id;
        }
    }
}();

zoo.form.MultiEntry.instance= {};
zoo.form.MultiEntry.init = function(entryId, fields) {
    multiEntry = new zoo.form.MultiEntry(entryId, fields);
    multiEntryId = multiEntry.getId();
    multiEntry.init();
}
zoo.form.MultiEntry.add = function(btn, fieldName) {
    var multiEntryId = btn.getAttribute('multi-entry-id')
    if (!multiEntryId) {
        multiEntry = new zoo.form.MultiEntry(btn, window[fieldName]);
        multiEntryId = multiEntry.getId();
        multiEntry.init();
    } else {
        multiEntry = zoo.form.MultiEntry.instance[multiEntryId];
    }
    multiEntry.addEntry();
    return true;
}

zoo.remove = function(e) {
    e = e || window.event;
    var ajxRemove = function() {
        Modalbox.hide();                                 
        new Ajax.Request(this.href, {
            method: 'get', 
            onSuccess: function(transport) {
                setTimeout(function() {
                    location.reload(true);
                    return;
                }, 500);
            }
        });       
        return true;
    }

    var setHandler = function() {
	$('deleteBut').observe('click', ajxRemove.bindAsEventListener(this));
        return true;
    }
    
    var node = new Element('div', {className: 'warning', style: 'display:none'}).update(
    new Element('p').update('Are you sure to delete this item?')
    ).insert(new Element('input', {type: 'button', value: 'Yes, delete it!', id: 'deleteBut'})).insert(
    new Element('span').update(' or ')
    ).insert(
    new Element('input', {type: 'button', value: 'No, leave it', id: 'cancelBut', onclick: 'Modalbox.hide()'})
    );
        
    Modalbox.show(node, {title: this.title, width: 600, afterLoad: setHandler, href: this.href });   
    Event.stop(e);
    return false;
}

zoo.Modalbox = function() {
    var bakAfterLoad, bakBeforeHide; 
    return {
        fitToScreen: function() {
            var modal_h = Modalbox.MBwindow.getHeight();
            var viewport_h = document.viewport.getHeight();
            if (modal_h > viewport_h) {
                Modalbox.MBwindow.style.height = viewport_h - 20 + 'px';
                Modalbox.MBcontent.style.height = viewport_h - 40 - Modalbox.MBheader.getHeight() + 'px';
                
            }
            if (bakAfterLoad) {
                backAfterLoad();
            }
            backAfterLoad = null;
        },
        
        show: function() {
    
            if (arguments[1].afterLoad) {
                var bakAfterLoad = arguments[1].afterLoad;
            }
            
            if (arguments[1].beforeHide) {
                var bakBeforeHide = arguments[1].beforeHide;
            }
            
            arguments[1].afterLoad = zoo.Modalbox.fitToScreen;
            arguments[1].beforeHide = zoo.Modalbox.cleanUp;
            
            Modalbox.show.apply(Modalbox, arguments);

        },
        
        resizeToContent: function() {
            var opts = { afterResize: zoo.Modalbox.fitToScreen };
            Modalbox.resizeToContent.apply(Modalbox, [opts]);
        },
        
        cleanUp: function() {
            if (zoo.form.Date.instanceArray.length) {
                zoo.form.Date.instanceArray.each(function(dateInput) {
                   dateInput.scal.closeCalendar();
                   dateInput.opened = false;
                });
                var scalCalendar = $('scal-calendar');
                if (scalCalendar) {
                    document.body.removeChild(scalCalendar);
                }
            }
            if (bakBeforeHide) {
                bakBeforeHide();
            }
            bakBeforeHide = null;
        }
    }
}();

/**
*
*  AJAX IFRAME METHOD (AIM)
*  http://www.webtoolkit.info/
*
**/

AIM = {

    frame : function(c) {

        var n = 'f' + Math.floor(Math.random() * 99999);
        var d = document.createElement('DIV');
        d.innerHTML = '<iframe width="100%" style="display:none" src="about:blank" id="'+n+'" name="'+n+'" onload="AIM.loaded(\''+n+'\')"></iframe>';
        document.body.appendChild(d);

        var i = document.getElementById(n);
        if (c && typeof(c.onComplete) == 'function') {
            i.onComplete = c.onComplete;
        }

        return n;
    },

    form : function(f, name) {
        f.setAttribute('target', name);
    },

    submit : function(f, c) {
        AIM.form(f, AIM.frame(c));
        if (c && typeof(c.onStart) == 'function') {
            return c.onStart();
        } else {
            return true;
        }
    },

    loaded : function(id) {
        var i = document.getElementById(id);
        if (i.contentDocument) {
            var d = i.contentDocument;
        } else if (i.contentWindow) {
            var d = i.contentWindow.document;
        } else {
            var d = window.frames[id].document;
        }
        if (d.location.href == "about:blank") {
            return;
        }

        if (typeof(i.onComplete) == 'function') {
            i.onComplete(d.body.innerHTML);
        }
    }

}


Event.observe(window, 'load', function() {
    zoo.dom.widgets.Hoverable();
    zoo.dom.widgets.ValuePrompt();
});

/* crap.. this needs to move under DOM */
function toggleEditor(id) {
    if (!tinyMCE.get(id))   
        tinyMCE.execCommand('mceAddControl', false, id);
    else    
        tinyMCE.execCommand('mceRemoveControl', false, id);
}