﻿"use strict";
/* This file contains utility functions which are generally useful in this project*/
var DFStyledDefaults = {
    validator : validateHelper
};

var SHIFT_DOWN = false;
var CTRL_DOWN = false;
var ALT_DOWN = false;
$(document).ready( function() {
    $(document).keydown( function(kev) {
        if( kev.keyCode == 16 ) { SHIFT_DOWN = true; } else
        if( kev.keyCode == 17 ) { CTRL_DOWN = true; } else 
        if( kev.keyCode == 18 ) { ALT_DOWN = true }
    }).keyup( function(kev) {
        if( kev.keyCode == 16 ) { SHIFT_DOWN = false; } else
        if( kev.keyCode == 17 ) { CTRL_DOWN = false; } else 
        if( kev.keyCode == 18 ) { ALT_DOWN = false }
    });
});
var weekdays = [ $.i18n.prop('Sunday'),
                 $.i18n.prop('Monday'),
                 $.i18n.prop('Tuesday'),
                 $.i18n.prop('Wednesday'),
                 $.i18n.prop('Thursday'),
                 $.i18n.prop('Friday'),
                 $.i18n.prop('Saturday')
                 ];

function bindMethod( object, method ) {
	return function () {
		return method.apply( object, arguments );
	}
}

function createDiv() { return $(document.createElement( "div" ) ); }

function trim(str, chars) {
	return ltrim(rtrim(str, chars), chars);
}

function ltrim(str, chars) {
	chars = chars || "\\s";
	return str.replace(new RegExp("^[" + chars + "]+", "g"), "");
}
 
function rtrim(str, chars) {
	chars = chars || "\\s";
	return str.replace(new RegExp("[" + chars + "]+$", "g"), "");
}

function arrContains( arr, element ) {
    for( var i = 0; i < arr.length; i++ ) {
        if( arr[i] == element ){
            return i;
        }
    }
    
    return -1;
}

function makeStyled( context, options ) {
    if( context ) {
        $("input[type=text]:not(.fugly)", context ).styled( DFStyledDefaults );
        $("input[type=password]:not(.fugly)", context).styled(DFStyledDefaults);
        $("input[type=radio]:not(.fugly)", context).styled(DFStyledDefaults);
        $("select:not(.fugly)", context ).styled( DFStyledDefaults ); 
        $("div.input-styledList", context ).styledList();
        $("div.styledToolMenu", context).styledToolMenu();
        /*$.each($("fieldset:not(.fugly) legend", context), function() {
            $(this).replaceWith($(document.createElement("DIV")).attr("class", "legend").html($(this).html()));
        });*/
    } else {
        $("fieldset:not(.fugly) input[type=text]:not(.fugly)").styled( DFStyledDefaults );
        $("fieldset:not(.fugly) input[type=password]:not(.fugly)").styled(DFStyledDefaults);
        $("fieldset:not(.fugly) input[type=radio]:not(.fugly)").styled(DFStyledDefaults);
        $("fieldset:not(.fugly) select:not(.fugly)").styled( DFStyledDefaults );
        $("fieldset:not(.fugly) div.input-styledList" ).styledList();
        $("div.styledToolMenu").styledToolMenu();
        /*$.each($("fieldset:not(.fugly) legend"), function() {
            $(this).replaceWith($(document.createElement("DIV")).attr("class", "legend").html($(this).html()));
        });*/
    }
}

function styled( context ) {
    if( context ) {
        $("input[type=text]:not(.fugly)", context ).styled( DFStyledDefaults );
        $("input[type=password]:not(.fugly)", context).styled(DFStyledDefaults);
        $("input[type=radio]:not(.fugly)", context).styled(DFStyledDefaults);
        $("select:not(.fugly)", context ).styled( DFStyledDefaults );
        
        //remove these after changing chemical bit
        $("div.input-styledList", context ).styledList();
        $("div.styledToolMenu", context ).styledToolMenu();
        return context;
    } else {
        $("input[type=text]:not(.fugly)").styled( DFStyledDefaults );
        $("input[type=password]:not(.fugly)").styled(DFStyledDefaults);
        $("input[type=radio]:not(.fugly)").styled(DFStyledDefaults);
        $("select:not(.fugly)").styled( DFStyledDefaults );
        $("div.input-styledList" ).styledList();
        $("div.styledToolMenu" ).styledToolMenu();
    }
}

function validateHelper(element) {
    var elemId = element.attr("id");
    var x = element.parents("form").eq(0).validate({
    showErrors: function(errors) {
            
            var tooltip = errors[elemId];
            if (tooltip) {

                var styled = element.data("styled");
                if (styled) {
                    styled.setButtonTooltip(tooltip);
                }
            }
        }
    });
    if (x) {
        x = x.element(element);
    } else {
        return -1;
    }
    var rules = element.rules();
    if (element.val() == "") {
        if (rules && rules.required) {
            return 2;
        } else {
            return -1;
        }
    }

    return x;
}

//StyledList element
jQuery.fn.styledList = function( options ) {
    this.each( function() {
        var _this = $(this);
        var _width = -1;
        var _height = -1;
        var inputSource = _this.attr( "inputSource" ) ? $( _this.attr( "inputSource" ) ) : null;
        var allowDuplicates = false;
        if( options ) {
            if( options.width != undefined ) {
                _width = options.width;
            }
            if( options.height != undefined ) {
                _height = options.height;
            }
            if( options.inputSource ) {
                inputSource = options.inputSource;
            }
            if(  options.allowDuplicates != undefined && options.allowDuplicates != false &&  
                options.allowDuplicates != "false" ) {
                allowDuplicates = true;
            }
        }
        if( _width == -1 ) {
            var attrWidth = _this.attr( "width" );
            if( attrWidth != undefined && attrWidth != null ) {
                _width = parseInt( attrWidth );
            } else {
                //our default width
                _width = 260;
            }
        }
        if( _height == -1 ) {
            var attrHeight = _this.attr( "height" );
            if( attrHeight != undefined && attrHeight != null ) {
                _height = attrHeight;
            } else {
                _height = 250;
            }
        }
        if( inputSource == null ) {
            //try to find the first input in the previous formfield
            inputSource = $( "select:first", _this.parent().prev() );
        }
        
        
        var _cWidth = _width - 41;
        var _cHeight = _height - 14;
        var _cHeightMargins = _height - 75;
        
        var styledElement = createDiv()
            .css( "width", _width + "px" )
            .css( "height", _height + "px" )
            .addClass( "ui-styledList" );
        var styledElementCanvas = createDiv()
            .css( "width", _cWidth + "px" )
            .css( "height", _cHeight + "px" )
            .addClass( "ui-styledList-canvas" );
            
        transferAttributes( _this, styledElement, "id, name" );
            
        styledElement.append( 
            createDiv().css( "float", "left" ).css( "width", "12px" ).css( "height", _height )
            .append(
                createDiv().addClass( "ui-styledList-nw" ) )
            .append(
                createDiv().addClass( "ui-styledList-cw" ).css( "height", _cHeightMargins + "px" ) )
            .append(
                createDiv().addClass( "ui-styledList-sw" ) ) ).append(
            
            createDiv().css( "float", "right" ).css( "width", "29px" ).css( "height", _height )
            .append(
                createDiv().addClass( "ui-styledList-ne" ).append(
                    createDiv().addClass( "ui-styledList-eGap" ) ).append(
                    createDiv().addClass( "ui-styledList-add" ).attr( "title", $.i18n.prop('AddItemToList') ).click( function() {
                        if( inputSource && inputSource.length > 0 ) {
                            var styledVal = inputSource.styledVal();
                            var valueId = styledVal.value;
                            var value = styledVal.text;
                            if( !valueId ) { valueId = value; }
                            if( !allowDuplicates ) {
                                //check for duplicacy
                                var isDuplicate = false;
                                $(".ui-styledList-item", styledElementCanvas ).each( function() {
                                    if( $(this).attr( "valueId" ) == valueId ) {
                                        isDuplicate = true;
                                        return;
                                    }
                                });
                                if( !isDuplicate ) {
                                    styledElementCanvas.append( createDiv().addClass( "ui-styledList-item" )
                                    .attr( "valueId", valueId ).html( value ).click( function() {
                                        $(this).toggleClass( "selected" );
                                    }) );
                                }
                            } else {
                                styledElementCanvas.append( createDiv().addClass( "ui-styledList-item" )
                                    .attr( "valueId", valueId ).html( value ).click( function() {
                                        $(this).toggleClass( "selected" );
                                    }) );
                            }
                        }
                    }) ).append( 
                    createDiv().addClass( "ui-styledList-remove" ).attr( "title", $.i18n.prop('RemoveSelectedItems') ).click( function() {
                        $(".ui-styledList-item.selected", styledElementCanvas ).remove();
                    }) ) )
            .append(
                createDiv().addClass( "ui-styledList-ce" ).css( "height", _cHeightMargins + "px" ) )
            .append( 
                createDiv().addClass( "ui-styledList-se" ) ) ).append(
            
            createDiv().css( "margin-left", "12px" ).css( "margin-right", "29px" )
                .css( "width", _cWidth + "px" ).css( "height", _height )
            .append(
                createDiv().addClass( "ui-styledList-nc" ).css( "width", _cWidth + "px" ) )
            .append( styledElementCanvas )
            .append(
                createDiv().addClass( "ui-styledList-sc" ).css( "width", _cWidth + "px" ) ) );
       
       _this.replaceWith( styledElement );
    });
    
    return this;
}

//styled Tool Menu element
jQuery.fn.styledToolMenu = function( options ) {
    this.each( function() {
        var _this = $(this);
        
        var title = _this.attr( "title" );
        if( options ) {
            if( !title ) {
                title = options.title ? options.title : "";
            }
        }
        
        var styledElement = createDiv().addClass( "ui-styledToolMenu" ).css( "height", "auto" );
        var head = createDiv().addClass( "ui-styledToolMenu-head" );
        _this.removeAttr( "title" ).removeAttr( "className" ).addClass( "ui-styledToolMenu-content" );
        var minimizeBt = createDiv().addClass( "ui-styledToolMenu-minimize" );
        var originalContentHeight = null;
        var originalContent = _this.html();
        var wrapper = createDiv().addClass( "ui-styledToolMenu-content-wrapper" ).css( "width", "auto" ).css( "height", "auto" );
        wrapper.html( originalContent );
        if( _this.attr( "id" ) ) {
            wrapper.attr( "id", _this.attr( "id" ) );
            _this.removeAttr( "id" );
        }
        _this.empty().append( wrapper );
        
        var collapsedAttr = _this.attr( "collapsed" );
        if( collapsedAttr && collapsedAttr != "false" ) { 
            _this.removeAttr( "collapsed" );
            styledElement.attr( "collapsed", "true" ); 
            originalContent = _this.html();
            originalContentHeight = _this.height();
            wrapper.css( "display", "none" );
            _this.css( "height", "2px" );
            minimizeBt.toggleClass( "ui-styledToolMenu-minimize", false );
            minimizeBt.toggleClass( "ui-styledToolMenu-maximize", true );
            minimizeBt.attr( "title", "Reveal Panel" );
        }
        
        var toggleToolPanel = function(ev) {
            if( minimizeBt.hasClass( "ui-styledToolMenu-minimize" ) ) {
                originalContentHeight = _this.height();
                originalContent = wrapper.html();
                _this.css( "height", originalContentHeight + "px" );
                //_this.empty();
                wrapper.css( "display", "none" );
                _this.animate({ height: "2px" }, 300 );
                minimizeBt.toggleClass( "ui-styledToolMenu-minimize", false );
                minimizeBt.toggleClass( "ui-styledToolMenu-maximize", true );
                minimizeBt.attr( "title", "Reveal Panel" );
                styledElement.attr( "collapsed", "true" );
            } else {
                _this.animate({ height: originalContentHeight + "px" }, 300, "swing", function() {
                    //_this.append( originalContent );
                    wrapper.css( "display", "block" );
                } );
                minimizeBt.toggleClass( "ui-styledToolMenu-maximize", false );
                minimizeBt.toggleClass( "ui-styledToolMenu-minimize", true );
                minimizeBt.attr( "title", "Minimize Panel" );
                styledElement.attr( "collapsed", "false" );
            }
            
            ev.stopPropagation();
        }
        
        //head.click( toggleToolPanel );
        styledElement.append( createDiv().addClass( "ui-styledToolMenu-headContainer" ).append( head
            .append(
                createDiv().addClass( "ui-styledToolMenu-close" ).click( function() {
                    alert( "Not possible yet!" );
                }) ).append(
                minimizeBt.click( toggleToolPanel ) ).append(
                $(document.createElement( "h3" )).html( title )
                ) ) )
                
        styledElement.append( _this.replaceWith( styledElement ) );
    }); 
    
    return this;
}

//String formatting
//Example Usage: '{0} {0} {1} {2}'.format(3.14, 'abc', 'foo');
String.prototype.format = function () {
    var s = this,
        i = arguments.length;

    while (i--) {
        s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), arguments[i]);
    }
    return s;
};

String.prototype.endsWith = function (suffix) {
    return (this.substr(this.length - suffix.length) === suffix);
}

String.prototype.startsWith = function (prefix) {
    return (this.substr(0, prefix.length) === prefix);
}

//converts a string to boolean where "true" is true, and any other value is false
String.prototype.toBoolean = function () {
    return this.toLowerCase() == "true";
}

//returns if the arrays are equal, ie no value in either array is not found in the other (duplicate values are allowed)
Array.prototype.equal = function (array) {
    if ($.isArray(this) && $.isArray(array)) {
        return this.contains(array) && array.contains(this);
    }
    return false;
}

//checks to see if the array [this] contains all the values within array [array]
Array.prototype.contains = function (array) {
    if (this.length) {
        if ($.isArray(array)) {
            var result = true;
            var self = this;
            if ($.isArray(array)) {
                $.each(array, function (k, v) {
                    result = result && $.inArray(v, self) != -1;
                });
            }
            return result;
        }
    }
    return false;
}


//selects a property from an array of objects
Array.prototype.select = function (property) {
    var result = new Array();
    $.each(this, function (k, v) {
        result[k] = v[property];
    });
}

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function (elt /*, from*/) {
        var len = this.length >>> 0;

        var from = Number(arguments[1]) || 0;
        from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
        if (from < 0)
            from += len;

        for (; from < len; from++) {
            if (from in this &&
          this[from] === elt)
                return from;
        }
        return -1;
    };
}

// searches an object for a child with the scope given
// hasOwnPropertyRecusive(obj, ['foo', 'bar']) returns true if obj is { 'foo': { 'bar':'someValue' } }
// useful for checking obj.foo.bar exists before making a call to it.
// this would have been added to the Object prototype, but jquery.validate.js doesn't like it because jquery includes the function on the each, and validate then attempts to access it as though it were an object.
function hasOwnPropertyRecusive(self, args) {
    if (self == null || args == null) {
        return false;
    }

    var result = true;
    var arrayRecurse;
    var obj = self[args[0]];
    if (args.length) {
        result &= obj != null; //first check to see if the object exists
        arrayRecurse = args.slice(1);
        if (result && arrayRecurse.length) {
            result &= hasOwnPropertyRecusive(obj, arrayRecurse);
        }
    }
    return result;
}
