/*------------------------------------------------------------------------
 * Logging function.  If the site is built with debugging enabled, then 
 * this function calls console.log.  When debugging is disabled, it defines
 * an empty function which does nothing.
 *------------------------------------------------------------------------*/

function log() {
}

/*------------------------------------------------------------------------
 * Functions to handle multiple handler for onload and onunload events.
 * Call page_onload(fn) and page_unload(fn) to register functions to be
 * call when the page is loaded/unloaded
 *------------------------------------------------------------------------*/

var onload_functions = new Array();
var unload_functions = new Array();

function onloader() {
//  log('running onloader()');
    for(var i = 0; i < onload_functions.length; i++) {
//      log('running onload function %d: %s', i, onload_functions[i]);
        try { onload_functions[i](); }
        catch(err) { 
            log('Caught error in onload function: ' + err);
        }
    }
}

function unloader() {
//  log('running unloader()');
    for(var i = 0; i < unload_functions.length; i++) {
        try { unload_functions[i](); }
        catch(err) {
            log('Caught error in unload function: ' + err);
        }
    }
}

function page_onload(func) {
//  log('registering onload %s', func);
    onload_functions.push(func);
}

function page_unload(func) {
//  log('registering unload %s', func);
    unload_functions.push(func);
}

$(document).ready(onloader);
//window.onload   = onloader;
window.onunload = unloader;


var weekdays = new Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");
var months   = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");

function update_clock() {
    var elem  = document.getElementById('clock');
    if (elem) {
        elem.innerHTML = clock_html();
    }
}

function clock_html() {
    var date  = new Date();
    var day   = date.getDate();
    var wday  = weekdays[date.getDay()];
    var mon   = months[date.getMonth()];
    var year  = date.getFullYear();
    var hours = date.getHours();
    var mins  = date.getMinutes();
    var secs  = date.getSeconds();
    var ordinal, ampm = 'am';

    if (mins < 10)
        mins = '0' + mins; 
    if (secs < 10)
        secs = '0' + secs; 

    if (day == 1 || day == 21 || day == 31) {
        ordinal = 'st';
    }
    else if (day == 2 || day == 22) {
        ordinal = 'nd';
    }
    else if (day == 3 || day == 23) {
        ordinal = 'rd';
    }
    else {
        ordinal = 'th';
    }
    
    if (hours > 11) {
        ampm = 'pm';
    }
    if (hours > 12) {
        hours -= 12;
    }

    return wday + ' '
         + day + '<span class="ordinal">' + ordinal + '</span> '
         + mon + ' ' + year + ' | ' 
         + hours + ':' + mins + ':' + secs + ' ' + ampm;
}


var CR = { 
    FT_TO_M:     0.3048,
    M_TO_FT:     3.2808,
    FT2_TO_M2:   0.0929,
    M2_TO_FT2:  10.7636,
    DO_NOTHING: function() { },

    // method to construct a new class - see editor.js for examples
    Class: function (schema) {
        schema.base     = schema.base || Object;
        schema.defaults = schema.defaults;

        // merge any defaults defined in the base class with those specified 
        // in the schema
        var defaults = jQuery.extend({ }, schema.base.defaults, schema.defaults);

        // define a constructor function that merges the class defaults and 
        // object configuration parameters into this.config then calls init()
        var cf = function(config) {
            if (config) {
                this.config = jQuery.extend({ }, defaults, config);
                this.init(this.config);
            }
        };
    
        // set the base class prototype and class defaults
        cf.prototype = new schema.base;
        cf.defaults  = defaults;
    
        // bind any methods specified in the schema
        if (schema.methods) {
            for (var m in schema.methods) {
                cf.prototype[m] = schema.methods[m];
            }
        }
    
        return cf;
    },
    blackout: function() {
        $('#blackout').fadeIn('fast', CR.loading);
    },
    loading: function() {
        $('#loading').show();
    },
    loaded: function() {
        $('#loading').hide();
        $('#overlay').fadeIn('fast');
    },
    overload: function(url) {
        CR.blackout();
        $('#overlay_content').load(url, CR.loaded);
        document.onkeyup = CR.help_key_handler;
    },
    overlay: function(html) {
        CR.blackout();
        $('#overlay_content').html(html);
        CR.loaded();
    },
    clear_overlay: function() {
        $('#blackout, #overlay').fadeOut('fast');
      document.onkeyup = "";
        return false;
    },
    help_key_handler: function(e) {
        var key = e == null
            ? event.keyCode         // IE
          : e.which;              // Mozilla

      if (key == 27) {            // escape
        CR.clear_overlay();
      } 
    },
    set_cookie: function(name, value, days) {
        var expires;
        if (days) {
            var date = new Date();
            date.setTime(date.getTime() + (days*24*60*60*1000));
            expires = "; expires=" + date.toGMTString();
        }
        else
            expires = "";
        document.cookie = name + "=" + value + expires + "; path=/";
    },
    get_cookie: function(name) {
        var namestr  = name + "=";
        var cookbits = document.cookie.split(';');
        var n;
        for(n = 0; n < cookbits.length; n++) {
            var c = cookbits[n];

            /* remove leading whitespace */
            while (c.charAt(0) == ' ')
                c = c.substring(1, c.length);

            /* if the name start this cookie fragment, return the value */
            if (c.indexOf(namestr) == 0)
                return c.substring(namestr.length, c.length);
        }
        return null;
    },
    save_element_class: function(id) {
//        var value = $('#' + id).attr('class');
//        alert('saving ' + id + ' as ' + value);
        CR.set_cookie(id + '_class', $('#' + id).attr('class'));
    },
    restore_element_class: function(id) {
//        alert('restoring ' + id);
        var value = CR.get_cookie(id + '_class');
        if (value) {
//            alert('setting ' + id + ' class to ' + value);
            $('#' + id).attr('class', value);
        }
    },
    persist_class: function(id) {
        CR.restore_element_class(id);
        page_unload( function() { CR.save_element_class(id) } );
    }
};

CR.HTML = {
    element: function(etype, attrs, ebody) {
        return '<' 
             + etype 
             + (attrs
                 ? CR.HTML.attrs(attrs) 
                 : '')
             + (ebody
                 ? '>' + ebody + '</' + etype + '>'
                 : '/>');
    },
    attrs: function(attrs) {
        var name, value;
        var chunks = [ ];
        for (name in attrs) {
            value = attrs[name];
            chunks.push(name + '="' + value + '"');
        }
        return chunks.length
            ? ' ' + chunks.join(' ')
            : '';
    }
};

CR.Base = CR.Class({
    methods: {
        // generic debug function - calls console.log() if firebug is running
        debug: function() {
            //  $('#console').append(sprintf.apply(sprintf, arguments) + '<br>');
            if (window.console && window.console.log) {
                window.console.log.apply(console, arguments);
            }
        },
    
        // call a method after a delay
        delay_method: function(delay, method, data) {
            var self = this;
            if (this.pending) {
                clearTimeout(this.pending);
            }
            this.pending = setTimeout( 
                function() { 
                    delete self.pending;
                    method.apply(self, data || []); 
                }, delay 
            );
        }
    }
});

page_onload(update_clock);

jQuery.fn.extend({
    solo_class: function(c) {
        this.addClass(c).siblings('.' + c).removeClass(c);
        return this;
    },
    // add 'warm' to class and remove from all siblings
    make_warm: function() {
        this.addClass('warm').siblings('.warm').removeClass('warm');
        return this;
    },
    // remove 'warm' class
    make_cold: function() {
        this.removeClass('warm');
        return this;
    },
    trim_val: function() {
        var value = this.val();
        if (value === undefined) {
            value = '';
        }
        else {
            value = value.trim();
        }
        this.val(value);
        return value;
    },
    num_val: function() {
        var input  = $(this);
        var value  = input.val().replace(/,/g, '').replace(/k$/ig, '000');
        var number = parseFloat(value);
    
        if (isNaN(number)) {
            if (value.length) {
                input.addClass('invalid');
            }
            return undefined;
        }
        else {
            // parseFloat() only returns first number in string so re-fill 
            // the field with the number we extracted
            input.val(number).removeClass('invalid');
            return number;
        }
    },
    impregnate: function(config) {
        config = config || { };
        var father = config.father;
        if (! father) { throw "No father specified to impregnate mother"; }
        return this.each(
            function () {
                new father(
                    jQuery.extend({ element: this }, config)
                );
            }
        );
    }
});


String.prototype.expand = function (o) {
    return this.replace(/(?:{|%7B)([^{}%]*)(?:}|%7D)/gi,
        function (a, b) {
            var r = o[b];
            return typeof r === 'string' || typeof r === 'number' ? r : a;
        }
    );
};

String.prototype.trim = function() {
  return this.replace(/^\s+|\s+$/g,'');
};

String.prototype.url_fragment = function() {
    /* Search from the start ('^') for any character that isn't '#' ('[^#]') 
     * repeated any number of times ('*') and replace it with nothing.
     */
    return this.replace(/^[^#]*/,'');
};

//Object.prototype.keys = function() {
//    var keys = [];
//    for(var key in this){
//        keys.push(key);
//    }
//    return keys;
//};

function require(filename) {
    var script = document.createElement('script');
    script.setAttribute("type", "text/javascript");
    script.setAttribute("src", filename);
    document.getElementsByTagName("head")[0].appendChild(script); 
}

var default_name     = 'Your Name';
var default_email    = 'Your Email Address';
var default_password = 'Your Password';

/* Function called when document is ready to apply any JS-only enhancements */


function enhance() {
//    log('enhancing');
    
    // TODO: add revealers to options in 
    
    //    var elem = document.getElementById('#login_password');
    var login = document.login;
    var elem  = login ? login.password : 0;
    if (elem) {
        elem.type = 'text';
        elem.value = default_password;
    }
    else {
//        log('no #login_password element');
    }
}

page_onload(enhance);

/* This is used to switch between the different the forms in the header.
 * See templates/library/site/forms
 */

function select_form(menu_elem, form_id) {
    $(menu_elem.parentNode).make_warm();
    $(menu_elem.getAttribute('rel')).make_warm();
}

/* when a text input field is focused we remove any default text in it */

function field_default(field,defval) {
    if (field.value == defval)
        field.value = '';
}

function undefault_name(field) {
    if (field.value == default_name)
        field.value = '';
}

function undefault_email(field) {
    if (field.value == default_email)
        field.value = '';
}
    

/* when a password field is focused we remove any default text in it 
 * and change it from a text field to a password field
 */

function undefault_password(field) {
    if (field.value == default_password) {
        field.value = '';
        field.type  = 'password';
    }
}

function undefault_login(login_form) {
    log("undefaulting email (%s) and password (%s) in login form", 
        login_form.email, login_form.password);
        
    undefault_email(login_form.email);
    undefault_password(login_form.password);
    return true;
}

function undefault_register(register_form) {
    log("undefaulting name (%s) and email (%s) in register form", 
        register_form.name, register_form.email);
        
    undefault_name(register_form.name);
    undefault_email(register_form.email);
    return true;
}        

function select_panel(tab) {
    var elem = $(tab);
    elem.parent('li').make_warm();
    $(elem.attr('href').url_fragment()).make_warm();
    return false;
}

function reveal_panel(revealer) {
    $(revealer).parent('div.panel').toggleClass('closed');
    return false;
}

function load_panel(revealer) {
    var link  = $(revealer);
    var panel = link.parent('div.panel');
    panel.toggleClass('closed');
    if (panel.hasClass('preload')) {
        panel.find('div.body').load( 
            append_url_path( 
                link.attr('href'),
                'ajax'
            ),
            function () { panel.removeClass('preload'); }
        );
    }
    return false;
}

function reload_panel(revealer) {
    var link  = $(revealer);
    link.closest('div.body').load( 
        append_url_path( 
            link.attr('href'),
            'ajax'
        )
    );
    return false;
}


function reveal_bugsy(revealer) {
    $(revealer).parent('div').toggleClass('closed');
    return false;
}

function unlock_panel(unlocker) {
//    log("unlocker: %s", unlocker);
//    $(unlocker).closest('div.lockable').each(function() { log('elem:%s', this) }).toggleClass('unlocked');
    $(unlocker).closest('div.lockable').toggleClass('unlocked');
    return false;
}

function lock_panel(unlocker) {
    $(unlocker).closest('div.lockable').removeClass('unlocked');
    return false;
}

function submit_if_selected(select) {
    var option = select.options[select.selectedIndex];
    if (option.value) {
        select.form.submit();
//        console.log('got value: ' + option.value);
//        this.form.submit()
    }
    else {
//        console.log('no value ');
    }
}

function show_submenu(id) {
    $('#' + id).show();
}

function hide_submenu(id) {
    $('#' + id).hide();
}

function add_filter(elem) {
    var that = $(elem);
    var name = that.val();
    $('#filter_by_' + name).fadeIn();
    $('#filter_by_' + name + '_option').hide();
    that.val('');
    return false;
}

function zap_filter(name) {
    $('#filter_by_' + name).fadeOut().find('input').val('');
    $('#filter_by_' + name + '_option').show();
    return false;
}

/*------------------------------------------------------------------------
 * help(link)
 *-----------------------------------------------------------------------*/

function help(link) {
    var url = randomise_url( $(link).attr('href') + '/ajax' );
    CR.overload(url);
    return false;
}

function lightbox(link) {
    var url = $(link).attr('href');
    CR.overlay('<img src="' + url + '" class="lightbox">');
    return false;
}

function jcrop(link) {
    var url = append_url_path( $(link).attr('href'), 'ajax' );
    $('#blackout').fadeIn('fast', function() { $('#loading').show(); });
    $('#overlay_content').load( url, function() {
        $('#loading').hide();
        $('#overlay').fadeIn('fast');
    });

  document.onkeyup = CR.help_key_handler;
    return false;
}

function close_help() {
    CR.clear_overlay();
}

function randomise_url(url) {
    // IE caches files loaded via AJAX so we might need to add a random param
    var joint = url.indexOf("?") == -1 ? '?' : '&';
    return url 
         + joint 
         + 'IEsucks=1&random=' 
         + ( new Date().getTime() ) 
         + Math.round( Math.random() * 1000 );
}

function append_url_path(url, path) {
    var bits = url.split('?');
    var base = bits.shift();        // everything before the first '?'
    
    // Rebuild the URL and collapse any multiple slashes that have been 
    // introduced, e.g. by joining /foo/ with /bar to get /foo//bar
    // but not if the preceding character is ':', as in http://blah.com/
    return [base, path]
        .join('/')                              
        .replace(/([^:])\/+/g, '$1/')       // collapse multiple slashes
        + (bits.length ? ('?' + bits.join('&')) : '');
}

function append_url_param(url, param, value) {
    var match;
    var regex = new RegExp(param + '=([^&]+)');
    if (match = url.match(regex)) {
        return url.replace(regex, param + '=' + value);
    } 
    var joint = url.indexOf("?") == -1 ? '?' : '&';
    return url + joint + param + '=' + value;
}

function append_url_random(url) {
    // IE caches files loaded via AJAX so we might need to add a random param.
    // Also used to refresh image src or element background image after an 
    // image has been cropped or modified in some other way
    return append_url_param( 
        url , 'random', 
        ( new Date().getTime() ) + Math.round( Math.random() * 1000 )
    );
}


// old version
function convert_size_field(rate,source,target) {
    var t = $(target);
    if (! t.val()) {
//        t.val( Math.round( $(source).val().replace(',','') * rate ) );
        t.val( Math.floor( $(source).val().replace(',','') * rate ) );
    }
}



/*------------------------------------------------------------------------
 * url_params()
 * 
 * Parse any parameters specified with the URL.  Used by the maps.
 *------------------------------------------------------------------------*/

function url_params() {
  var url = window.document.URL.toString();
    var params = new Array;

    if (url.indexOf('?') > 0) {
        var args = url.split('?')[1].split('&');
    for (var i = 0; i < args.length; i++) {
      var tokens = args[i].split("=");
            params[tokens[0]] = tokens[1].length
                              ? unescape(tokens[1]) : '';
    }
  }

    return params;
}

/*------------------------------------------------------------------------
 * rel=external
 * 
 * Opens links in a new window. inserted by squeeze.
 *------------------------------------------------------------------------*/

function externalLinks() {
    var popup = function(){
        window.open(
            this.href, 
            'SubscribeWindow', 
            'toolbar=no,menubar=no,height=400,width=600,location=no,scrollbars=yes,resizable=no,status=no,left=30,top=30'
        );
    };
    $('a[rel="external"]').attr('target', '_blank');
    $('a[rel="popup"]').click(popup).keypress(popup);
}
page_onload(externalLinks);

