// Edit these settings
var
   //base_url = 'http://dev.sna.pr',
   //client_id = 'client',
   //client_secret = 'secret',
    base_url = 'https://sna.pr',
    client_id = '76e5be0eec71b28fb4380b0ac42201cf',
    client_secret = 'd293011a0a17dfc8aa191455af4ab7ba',
    appmode = window.location.protocol == 'file:',
    demo_mode = false,

// you shouldn't need to edit below    
    dom_cache = {},
    requests = [],  //list of currently active ajax requests
    $body,
    api_url = base_url+'/api',
    access_token_url = base_url+'/ext/oauth/access_token/',
    access_token,
    snapr_user,
    params,
    new_user = false,
    autoUpload = "radio-upload-wifi",
    location_callbacks = [],
    location_error_callbacks = [],
    upload_mode = 'On',
    upload_paused = false,
    geolocation_enabled = true,
    current_page = {
        hash: '',
        activate: $.noop,
        is_menu: true
    },
    previous_upload_count,
    dark_overlay = false,
    ajax_timeout = 25000,
    ajax_timeout_offline = 5000,
    click_action = 'vclick'; //either 'click' or 'vclick'. not using vclick for android as vclick seems to trigger double clicks which causes a lot of problems.

retreive_user_credentials();

function set_ajax_timeout(timeout){
    if(window.location.port=="8001"){return;} // Timeout leave me alone, please!

    $.ajaxSetup({
        timeout: timeout,
        // timeout: 1,  // uncomment to test what happens if there's a network error
        beforeSend: function(xhr){
            //keep a list of active requests, so we can choose to abort them
            requests.push(xhr);
        },
        error: function(request, status, maybe_an_exception_object) {
            if(status != 'timeout') {
                //notification("Application Error. Sorry!");
            } else {
                if($('body.offline')){
                    // no alert since we're already offline
                    $('.offline-message').remove();
                    $('#offline-message-tmpl').tmpl({}).prependTo('#page-content');
                }else{
                    approve({
                        'title':'There seems to be a problem connecting to the network. Would you like to try again?',
                        'yes':'Retry',
                        'yes_callback': function(){
                            location.reload(true);
                        },
                        'no_callback': function(){
                            abort_active_requests();
                            //console.warn('go offline');
                            $('body').addClass('offline');
                            // console.warn('offline-message-tmpl',$('#page-content'),$('#offline-message-tmpl').tmpl({}));
                            $('.offline-message').remove();
                            $('#offline-message-tmpl').tmpl({}).prependTo('#page-content');
                            set_ajax_timeout(ajax_timeout_offline);
                        }
                    });
                }
            }
        },
        complete: function(jqXHR, textStatus){
            //console.warn(jqXHR, textStatus);
            switch(textStatus){
                case 'success':
                    go_online();
                    break;
                case 'timeout':
                    go_offline();
                    break;
            }
        }
    });
}

set_ajax_timeout(ajax_timeout);

function go_online(){
    $('body').removeClass('offline');
    set_ajax_timeout(ajax_timeout);
    //console.warn('online now');
}
function go_offline(){
    $('body').addClass('offline');
    window.upload_paused = true;
    spinner_stop();
    set_ajax_timeout(ajax_timeout_offline);
    //console.warn('offline now');
}

function spinner_start(){
    $('body').addClass('n-loading');
    // if(appmode=="iphone"){
    //     $('body').addClass('n-loading-appmode');
    //     window.location = 'snapr://spinner?show';
    // }
}
function spinner_stop(){
    $('body').removeClass('n-loading');
    // if(appmode=="iphone"){
    //     $('body').removeClass('n-loading-appmode');
    //     window.location = 'snapr://spinner?hide';
    // }
}

function pass_data(url){
    window.location = url;
}

function change_location(url) {
    if (appmode == 'android') {
        pass_data('snapr://link?url=' + escape(url));
    } else {
        window.location.href = url;
    }
}

// send access token if set with all ajax requests
$.ajaxPrefilter( function( options, orig_options ) {

    // sneak POSTs over GET for cross domain
    if( options.crossDomain && orig_options.type == 'POST' ){
        options.data += '&_method=POST';
    }

    // add access token
    if ( access_token ) {
        options.data += '&access_token=' + access_token;
    }
});

function abort_active_requests() {
   $.each(requests, function(i, request) {
       request.abort();
   })
   requests = [];
}

// allows logging calls to be left in and will only show them when enabled
// inside the switch statement below
function log(namespace){
    //var fun = console.log; Illigal invocation!
    var fun = function(){
        try{
            console.log.call(arguments);  // FF
        }
        catch(webkit_fail){
            console.log(arguments);  // safari/chrome
        }
    };

    if(!window.console || !window.console.log){
        fun = $.noop; // alert(); // $.noop; // use noop to do nothing instead of alert.
    }

    switch(namespace){
        case undefined:
        // Add namespaces to be logged here
        // case 'click_capture':
        //case 'hashchange':
        //case 'load_overlay':
        //case 'popular':
        //case 'dash_autocomplete':
        //case 'signup':
        //case 'scroll':
            return fun;
    }
    return $.noop;
}
    
// get params from url
params = get_url_params();

if (appmode && appmode == 'android') {
    click_action = 'click';   //vclick from the currently used jqmobile is not working reliably in android (get a lot of double clicks)
} else {
    click_action = 'vclick';
}

$(function() {
    $body = $('body')
    .toggleClass('loggedin', !!access_token);

    if (!appmode && !demo_mode) {
           $('body').addClass('mobileweb');
    }


    dom_cache.n_overlay = $('#n-overlay');
    dom_cache.n_view = $('#n-view');

    // fix mobile safari failure to bubble click events up - see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
    if($('#page-wrapper')[0]){
        $('#page-wrapper')[0].onclick = function () {};
    }
    if(dom_cache.n_overlay[0]){
        dom_cache.n_overlay[0].onclick = function () {};
    }
    if(dom_cache.n_view[0]){
        dom_cache.n_view[0].onclick = function () {};
    }

    $(window).bind("hashchange", function(e, triggered){


        abort_active_requests();
        log('hashchange')("hashchange");

        params = get_url_params();
        log('hashchange')("params:", params);

        log('hashchange')("triggered:", triggered);

        log('hashchange')("menu:", !window.location.hash || /^#(\/?\?.*)?$/.test(window.location.hash));
        if( !window.location.hash || /^#(\/?\?.*)?$/.test(window.location.hash) ){
            dom_cache.n_overlay.hide();
            dom_cache.n_view.hide();
            spinner_stop();
            close_overlay();
            current_page.hash = window.location.hash;
            current_page.is_menu = true;
            update_menu_activity_message();

        }else{
            // show

            dom_cache.n_view.empty()
            if (dark_overlay) {
                dom_cache.n_view.addClass('dark-overlay');
            } else {
                dom_cache.n_view.removeClass('dark-overlay');
            }

            if (params.modal) {
                dom_cache.n_view.addClass('modal');
            } else {
                dom_cache.n_view.removeClass('modal');
            }

            dom_cache.n_view.show();


            spinner_start();

            $.ajax({
                dataType: 'html',
                url: window.location.hash.replace('#', ''),
                success: function(response){
                    var content = $(response);
                    dom_cache.n_view.append(content);

                    content.page();
                    current_page.activate();
                    current_page.hash = window.location.hash;
                    current_page.is_menu = false;
                    if(demo_mode){n_view_scroll =  new iScroll('n-view', demo_scroll_options);}
                    $('#n-view .snapr-page-titlebar').toggleClass('back-link', !!params.back);
                    if(params.back && params.back != 'true'){
                        $('#n-view .navbt-back .accessibility-text').text(params.back);
                    }
                    close_overlay();

                    $('#snapr-searchform').hide();
                },
                complete: function(){
                    // do nothing - prevent default setting of online to true
                }
            });
        }
    })
    .trigger("hashchange", [true]);

    if(new_user){
        load_overlay('welcome.html');
        delete new_user;
    }

    // signup with twitter
    if(params['twitter_token']){
        twitter_token = params['twitter_token'];
        delete params['twitter_token'];
        document.location.hash = add_extra_params('#join-snapr.html?snapr_username='+params['username']+'&from_twitter=true');
    }
    // signup with facebook
    if(params['facebook_token']){
        facebook_token = params['facebook_token'];
        delete params['facebook_token'];
        document.location.hash = add_extra_params('#join-snapr.html?snapr_username=' + params['username'].replace(' ','') + '&from_facebook=true');
    }

    $('a').die('click')  // tell jQmobile to leave my links alone, otherwise it will make them work even if I call e.preventDefault. Unfortunately this will break any other live click events bound above here.
       .live(click_action, function(e){ handle_anchor_click(this, e) });
        //temporarily trying vlick to see if it works

    function handle_anchor_click(anchor, e) {
        log('click_capture')("caught a click");
        if ($(anchor).data('dark-overlay')) {
            dark_overlay = true;
        } else {
            dark_overlay = false;
        }

        var href = $(anchor).attr('href'),
            orig = href;

        // mike's note: after the upgrade from 1.0a3 to 1.0a4, collapsible
        // headings started triggering hash change events, so I prevented this
        // by adding .ui-collapsible-heading-toggle here
        if(
            !href
            || href.match(/^\w+:\/\//i)  // external
            || $(anchor).is('[rel="external"]')  // external specified jQmob style
            || $(anchor).is('.no-n')
            || $(anchor).is('.ui-collapsible-heading-toggle')
            || $(anchor).is('.ui-input-clear')
        ){
            log('click_capture')("non nav");
            return
        }


        if(href.charAt(0) == '#'){
            log('click_capture')("is hash link:", add_extra_params(href));
            document.location.hash = add_extra_params(href);
            e.preventDefault();
            return
        }
        href = add_extra_params(href);
        log('click_capture')("changing href to:", href);

        if(href != orig){
            $(anchor).attr('href', href);
        }

    }


    $('a.n-overlay').live('click', function(e){
        var $this = $(this),
            href = $this.attr('href');

        if(!href){
            return true; // do whatever you do then
        }

        load_overlay(href);

        e.preventDefault();
    });

    $('.main-link:not(.n-refresh, .n-close), .n-back').live('click', function(e){
//        if(params.back_url){
//            window.location.href=params.back_url;
//        }else{
//            history.go(-1);
//        }
        back();
    });

    $('a.n-close').live('click', close_overlay);

    $('.x-login').live('click', function(e){
        e.preventDefault();
        login_required(refresh)()
    });
    $('.x-logout').live('click', function(e){
        e.preventDefault();
        logout();
    });

    $('.x-go-online').live('click',function(e){
        ajax_timeout = 25000;
        if(current_page.is_menu){
            $('body').removeClass('offline');
            update_menu_activity_message();
            setInterval(update_menu_activity_message, 60000);
        }else{
            spinner_start();
            location.reload(true);
        }
    })


    // quicksearch - home page
    $('#page-wrapper .x-quick-search').bind(click_action, function(){
        $('#snapr-searchform').toggle();
    });
    $('#page-wrapper .x-quick-search-close').bind(click_action, function(){
        $('#snapr-searchform').hide();
    });

    // quicksearch - n_view
    $('#n-view .x-quick-search').live(click_action, function(){
        $('#n-view .snapr-searchform').toggle();
    });
    $('#n-view .x-quick-search-close').live(click_action, function(){
        $('#n-view .snapr-searchform').hide();
    });


    $('.n-refresh').live('click', refresh);

    $('#snapr-searchform form').submit(function(e) {
        var search_type = $('#snapr-searchform #quicksearchtype');
        var search_query = $('#snapr-searchform #quicksearch');
        $('#snapr-searchform').hide();
        submit_quicksearch(search_type, search_query);
        e.preventDefault();
    });

    $('#n-view .snapr-searchform form').live('submit', function(e){
        var search_type = $('#n-view .snapr-searchform #quicksearchtype');
        var search_query = $('#n-view .snapr-searchform #quicksearch');
        submit_quicksearch(search_type, search_query);
        e.preventDefault();
    });

    function submit_quicksearch(search_type, search_query) {
        switch(search_type.val()){
            case 'tag':
                window.location.hash = add_extra_params('#feed.html?keywords='+search_query.val());
                break;
            case 'user':
                window.location.hash = add_extra_params('#people.html?username='+search_query.val());
                break;
            case 'location':
                window.location = add_extra_params('map.html?location='+search_query.val());
                break;
        }
    }

    // follow
    /*
    $('.x-follow').live('click', function(){
        if( !logged_in ){
            redirect_to_login();
        }
        var $this = $(this),
            username = $this.data('username');
                
        $this.addClass('ajax');
                
        $.ajax({
            url: api_url+'/user/follow/',
            type: 'POST',
            dataType: 'json',
            data:{ username: username },
            success: function(response){
                $this.removeClass('ajax');
                if(response.success){
                        $('#page-wrapper').removeClass('follow').addClass('following');
                        var count = parseInt($this.data('count'))+1;
                        $('.x-followers-count.x-user-'+username).text(count);
                        $this.data('count', count);
                }else{
                        notification(response.error.message);
                }
            }
        });
    });
        
    $('.navbt-following a').live('click', function(){
        if( !logged_in ){
            redirect_to_login();
        }
        
                var button = $(this),
                        user_info = $('#user-info'),
                        id = user_info.data('id');
                        
                button.addClass('ajax');
                
        $.ajax({
            url: api_url+'/user/unfollow/',
            type: 'POST',
                        dataType: 'json',
            data:{ user_id: id },
            success: function(response){
                button.removeClass('ajax');
                if(response.success){
                        $('#page-wrapper').removeClass('following').addClass('follow');
                        var followers = user_info.find('.user-followers .stats-number'),
                                count = parseInt(followers.data('count'))-1;
                        followers.text(count).data('count', count);
                }else{
                        notification(response.error.message);
                }
            }
        });
    });

    */

    /* login with linked services
    *****************************/
    $('.x-login-service').live(click_action, function(){
        if(!appmode){
            spinner_start(); 
        }
       
        var service = $(this).data('service');

        here = window.location.href;
        here += (here.indexOf('#') == -1) && '#' || '';
        here += (here.indexOf('?') == -1) && '?' || '&';
        here += service + '_success=true';

        // app_mode redirect
        if(appmode){
            here = 'snapr://redirect?url=' + escape(here)
        }
        url = base_url+"/api/linked_services/"+service+"/signin/?display=touch&client_id="+client_id+"&client_secret="+client_secret+"&redirect="+escape(here);
        console.log(url);
        change_location(url);
    });

    // I dont think we ever want to show welcome.html on the web.. so can we nix this??
    
    // if(!access_token && appmode){
    //          if (supports_local_storage()) {
    //             if (!localStorage["snapr.not-first-time"]) {
    //                 load_overlay('welcome.html');
    //                 localStorage["snapr.not-first-time"] = true;
    //             }
    //          } else {
    //              load_overlay('welcome.html');
    //          }
    //     }

    if (snapr_user) {
        if (!appmode) {  // only do this if we're on mobile web. Not necessary in app_mode and a bit kludgey
            if (params.twitter_success && window.location.href.indexOf('access_token') > -1) {
                strip_tokens_from_url_and_refresh();
            }
        }
        if (params.twitter_success) {
            notification('Signed in as ' + snapr_user);
        }

        if (!appmode) {  // only do this if we're on mobile web. Not necessary in app_mode and a bit kludgey
            if (params.facebook_success && window.location.href.indexOf('access_token') > -1) {
                strip_tokens_from_url_and_refresh();
            }
        }
        if (params.facebook_success) {
            notification('Signed in as ' + snapr_user);
        }
    }

    //no need to do this the first time, because hashchange triggers an 'update_menu_activity' if we are on menu.html
    setInterval(update_menu_activity_message, 60000);

    stretch_menu();

    //android hack for visual feedback when a link is touched (simulate mouseover)
    $('.droid-btn')
            .live('touchstart', function() {
                $(this).addClass('active');
            })
            .live('touchend', function() { $(this).removeClass('active');})
            .live('touchmove', function() { $(this).removeClass('active');});
});

function stretch_menu() {
    //make menu fill screen for different screen resolutions
    var height_3up_buttons = Math.floor($(window).width() / 3);
    $('.menu-icons-3up .menu-icon a').css('height', height_3up_buttons);
    var window_height = $(window).height();
    var remainder_height = window_height - (2 * height_3up_buttons) - $('.snapr-page-titlebar').height() - $('.menu-activity-bar').height();
    $('.menu-icons-2up .menu-icon a').css('height', remainder_height - 2);
}


// used for twitter and facebook login for mobile, where we are redirected with tokens in the url (only way to remove them from url is to refresh)
function strip_tokens_from_url_and_refresh() {
    var prev_location = window.location.href;
    var regex1 = /(.*)(&access_token=[\w^&]+)(.*)/;
    var new_location = prev_location.replace(regex1, "$1$3");
    var regex2 = /(.*)(&snapr_user=[\w^&]+)(.*)/;
    new_location = new_location.replace(regex2, "$1$3");
    change_location(new_location);
}

// alert/confirm replacements
function notification(title, text, callback){
    var context = this;
    if (appmode == 'iphone'){
        var par = {
            'title': title,
            'otherButton1': 'OK',
            'alertID': 0
        }
        if(text){par.message = text;}
        if(window.override && window.override('snapr://alert?'+$.param(par))){
            //do nothing
        }else{
            window.location.href='snapr://alert?'+$.param(par);
        }
        
    }else{
        if(text){
            title = title + ' ' + text;
        }
        alert(title);
        if($.isFunction(callback)){
            $.proxy(callback, context)();
        }
    }
}
function approve(options){
    var context = this;
    options = $.extend({
        'title': 'Are you sure?',
        'yes': 'Yes',
        'no': 'Cancel',
        'yes_callback': $.noop,
        'no_callback': $.noop
    }, options);

    if (appmode == 'iphone'){
        actionID = tapped_action.add(options.yes_callback, options.no_callback);
        window.location.href = 'snapr://action?'+$.param({
            'title': options.title,
            'destructiveButton': options.yes,
            'cancelButton': options.no,
            'actionID': actionID
        });
    }else{
        if(confirm(options.title)){
            $.proxy(options.yes_callback, context)();
        }else{
            $.proxy(options.no_callback, context)();
        }
    }
}
// what the app calls after an approve
function tapped_action(alertID, buttonIndex){
    tapped_action.alerts[alertID][buttonIndex]();
    delete tapped_action.alerts[alertID];
}
tapped_action.alerts = {};
tapped_action.counter = 1;
tapped_action.add = function(yes, no){
    id = tapped_action.counter++;
    tapped_action.alerts[id] = {'-1': yes, '0': no};
    return id;
}

function get_location(success, error){
    // if in appmode, ask the app for location, otherwise try html5 geolocation
    if(appmode){
        // TODO: what is there is no response!? need timeout function.
        location_callbacks.push(success);
        location_error_callbacks.push(error);
        if(window.override && window.override('snapr://get_location')){
            //do nothing
        }else{
            if (appmode == 'android') {
                // android locks up the UI for like 30 seconds whenever it tries to lookup the location, so we are caching the curr location, and only getting the
                // new location is if the cached value is greater than 5 minutes old. TODO: this should really be done android-side

                var cached_location = get_cached_geolocation();
                if (cached_location != null) {
                    success(cached_location);
                } else {
                    window.location = 'snapr://get_location';
                }
            } else {
                window.location = 'snapr://get_location';
            }
        }

    }else{
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(success, error);
        }else{
            error('Geolocation is not supported by your browser.')
        }
    }
}


/* only used for android */
function get_cached_geolocation() {
    if (supports_local_storage()) {
        var now = new Date().getTime();
        if (localStorage.getItem('curr_geolocation') != undefined
            && now < localStorage.getItem('geolocation_cache_expires')) {
            return JSON.parse(localStorage.getItem('curr_geolocation'));
        } else {
            return null;
        }
    } else {
        return null;
    }
}


/* only used for android */
function set_cached_geolocation(location) {
    var geolocation_cache_time = 1000*60*5; //5 minutes in milliseconds
    if (supports_local_storage()) {
        var now = new Date().getTime();
        if (localStorage.getItem('geolocation_cache_expires') == undefined
            || localStorage.getItem('geolocation_cache_expires') < now)
        {
            localStorage.setItem('geolocation_cache_expires', now + geolocation_cache_time);
            localStorage.setItem('curr_geolocation', JSON.stringify(location));
        }
    }
}

function set_location(latitude, longitude){
    while(location_callbacks.length){
        location_callbacks.pop()(
            {'coords':{'latitude':latitude, 'longitude': longitude}}
        );
    }
}
function location_error(error){
    while(location_error_callbacks.length){
        location_error_callbacks.pop()(error);
    }
}

function set_appmode(){
    appmode=true;
}

function set_geolocation_enabled(enabled){
    geolocation_enabled=enabled;
    $('body').toggleClass('location-blocked', !enabled);
}

/**
 *
 * @param upload_mode  (string) possible values: 'On', 'Wi-Fi Only', 'Stopped'
 * @param paused: (boolean) or string. eg: either true or 'true'
 */
function queue_settings(upload_mode, paused) {
    window.upload_mode = upload_mode;

    if (paused == 'true' || paused == true) {
        window.upload_paused = true;
    } else {
        window.upload_paused = false;
    }
    if (window.upload_paused) {
        $('#options-queue').addClass('queue-paused');
    } else {
        $('#options-queue').removeClass('queue-paused');
    }

    $('input[name="radio-upload-settings"]').each(function() {
        var val = $(this).val();
        if(val == upload_mode) {
            $(this).attr("checked","checked");
            var text_val = val;
            if (val == 'On') { text_val = 'Uploads On'; }
            $('#upload-mode-label').text(text_val);
        }
    }).checkboxradio("refresh");
}


function upload_progress(data, datatype) {
    //data may be passed as an object or a string as specified via the data_type param 
    // defualts to JSON object, if 'json_string' it will be a text string that needs to be parsed..    
    //dont foget to convert it before you do anything with it..
     if (datatype == 'json_text') {
        data = JSON.parse(data);
        //console.log("UPLOAD: datatype 'json_text' recognised. doing JSON.parse" + data);
    }
   
    if(data.uploads.length){
        if (typeof datatype == undefined) {
            datatype = 'json';
        }

        if (params.username && (params.username == snapr_user)) {
            //console.log("UPLOAD: recognised that we are on my snaps page. showing progress");

            var queue_list = $('#active-queue-list');
            //queue_list.find('.x-thumb').remove();


            // if (global_upload_count && global_upload_count > 0) {
                
                var queue_list = $('#active-queue-list');
                queue_list.removeClass('no-results');
                //add the image items to the list
                for (var i = 0; i < global_upload_count; i++) {
                    $("#dummy-active-queue-template").tmpl().appendTo(queue_list);
                }
                //if paused show the blue title bar to say why the queue is paused

                if(upload_mode == 'Stopped' || upload_mode == 'Wi-Fi Only' || upload_paused){
                    $('#active-queue-list .dummy').remove();
                    if($('#queue-setting-helper').length ==0){
                        $('#paused-upload-title-template').tmpl({upload_mode:upload_mode, upload_paused:upload_paused }).insertBefore('#active-queue-list');
                    }
                    $('#active-queue-list').addClass('waiting');
                }
            // }

            var new_ids = [];
            queue_list.find('.dummy').remove();

            $.each(data.uploads, function(index, item) {
                new_ids.push(String(item.id));
                var line_jq = queue_list.find('li[data-id=' + item.id + ']');
                if (line_jq.length) {
                    var line = $(line_jq[0]);
                    $.each(['waiting','active','canceled','hold'], function(i, status){
                        line.toggleClass(status, item.upload_status==status);
                    });
                    line.find('.percent-complete').text(item.percent_complete);
                    line.find('.upload-status').text(item.upload_status);
                    //console.log("UPLOAD: updating progress of an upload item");
                    line.find('.active-text').text(item.upload_status);
                    line.find('.bar-prog').css('width', item.percent_complete+"%");
                    line.toggleClass('processing', item.percent_complete == 100);
                   
                } else {
                    $("#active-queue-template").tmpl(item).appendTo(queue_list);
                    //console.log("UPLOAD: added new upload item");
                }
            });
            //remove lines that have completed
                //get all ids that are currently in the list
                var current_ids = [];
                queue_list.find('.active-download').each(function() {
                    current_ids.push(String($(this).data2('id')));
                });

                $.each(current_ids, function(index, id){
                    if ($.inArray(id, new_ids) == -1) {
                       queue_list.find('li[data-id=' + id + ']').slideUp();
                       //console.log("UPLOAD: finished an upload item");
                    }
                });
                if (new_ids.length == 0) {
                    $('.active-uploads-header').slideUp();
                }

            queue_list.listview('refresh');
            queue_list.removeClass('no-results');
        }
    }else{
        if(appmode){
            pass_data('snapr://upload_progress?send=false');
        }
    }

}

var global_upload_count = null;
function upload_count(count) {
    //console.log('UPLOAD: upload_count() called');
    global_upload_count = count;
    previous_upload_count = count;

    if (count > 0) {
        //console.log('UPLOAD: updating count on menu page');
        $('.upload-count').show();
        $('.upload-count').text(count);
    } else {
        $('.upload-count').hide();
        $('#queue-setting-helper').slideUp(400,function(){$(this).remove()});
    }
}
function upload_completed(queue_id, snapr_id){
    if(current_page.slug=='feed'){
        $('#active-queue-list li[data-id=' + queue_id + ']').slideUp(400,function(){$(this).remove()});
        //console.log("UPLOAD: finished upload item " + queue_id + ' with snapr_id ' + snapr_id);
        spinner_start();
        var current_total = parseInt($('.user-photos .stats-number').text()) || 0;
        $('.user-photos .stats-number').text(current_total +1);   
        load_photos(params, true);
    }
    
    // if(current_page.slug == 'upload-points' && params.unique_id == queue_id){
    //     delete params.unique_id;
    //     params.photo = snapr_id;
    //     current_page.activate();
    // }else if(current_page.slug == 'feed'){
    //     load_photos(undefined, true);
    // }
}

function upload_cancelled(id){
    $('#active-queue-list li[data-id=' + id + ']').slideUp(400,function(){$(this).remove()});
}

function load_user_header(username, callback){

    // show basic header until real one loads
    $('#user-info').replaceWith( $( "#temp-user-header-template" ).tmpl( {"username" :username} ) );

    $.ajax({
        url: api_url+'/users/details/',
        dataType: 'jsonp',
        data:{'username': username },
        success: function(response){
            if(response.success){
                $('#user-info').replaceWith( $( "#user-header-template" ).tmpl( response.response ) );
                
                if(callback){
                    callback(response);
                }

            }else{
                notification(response.error.message);
            }
        }
    });
};


function add_extra_params(href){

    //$.each(['access_token', 'snapr_user', 'latitude', 'longitude', 'demo_mode'], function(i, v){  //tokens now stored locally
    $.each(['latitude', 'longitude', 'appmode', 'demo_mode'], function(i, v){
        if ( window[v] &&  (href.indexOf(v+'=') == -1) ) {
            href += (href.indexOf('?') == -1) && '?' || '&';
            href += v+'='+window[v];
        }
    })

    return href;
}

function get_url_params(){
    var params = {};
    
    if (window.location.hash.indexOf('?') !== -1){
        var query = window.location.hash.split('?')[1];  // remove the "?"
        $.each(query.split('&'), function(i,v){
            var kv = v.split('=');
            params[kv[0]] = unescape(kv[1]);
        });
    }

    // move params to global and delete
    $.each(['access_token', 'snapr_user', 'appmode', 'new_user', 'demo_mode'], function(i, v){
        if(params[v]){
            window[v] = params[v];
            delete params[v];
        }
    })

    // copy params to global without deleting
    $.each(['latitude', 'longitude'], function(i, v){
        if(params[v]){
            window[v] = params[v];
        }
    })
    if( params['appmode'] ) {
        set_appmode();
    }
    if( params['upload'] ) {
        autoUpload = params['upload'];
    }

    return params;
}

function load_overlay(url, callback){
    log('load_overlay')(url)

    spinner_start();
    dom_cache.n_overlay.empty().show().css({
        'height': $(document).height()
    });


    $('body').css({scrollTop : 0});
    log('load_overlay')('Requesting Overlay')
    $.ajax({
        dataType: 'html',
        url: url,
        success: function(response){
            log('load_overlay')('got overlay')
            var content = $(response);
            log('load_overlay')('created overlay dom elements')
            dom_cache.n_overlay.append(content);
            log('load_overlay')('appended overlay')


            if(content.page){
                content.page();
            }
            log('load_overlay')('jQmobile enhnaced overlay')

            if(demo_mode){
                n_overlay_scroll = new iScroll('n-overlay', demo_scroll_options);
                log('load_overlay')('applied overlay scolls')
            }
            spinner_stop();
            if(callback){
                callback(dom_cache.n_overlay);
            }
        }
    });
}

function close_overlay(e){
    dom_cache.n_overlay.hide();
    e && e.preventDefault();
};

/*
* Decorator
* takes a function and returns a copy of it that will execute if logged in or show login if not
* use: $('.things').click( login_required(function(e){ Actions }) );
*  or: login_required(refresh)(); // shows login or refreshes.
*/
function login_required(funct){
    return function(e){
        if(!access_token){
            if(e){
                e.preventDefault();
            }
            load_overlay('login.html');
            window.scrollTo(0,0);
        }else{
            $.proxy(funct, this)(e);
        }
    };
}

function login(username, password, callback){

    $('#snapr-loginform').addClass('loading');
    $.ajax({
        url: access_token_url,
        type: 'POST',
        dataType: 'jsonp',
        data:{
                'grant_type':'password',
                'client_id':client_id,
                'client_secret':client_secret,
                'username': username,
                'password': password
        }
    }).done(function(response){
        $('#snapr-loginform').removeClass('loading');
        if(response.error){
            if(response.error_description == "The provided access grant is invalid. (username and password invalid)."){
                notification("Sorry, we don't recognise your username and password");  
            }else{
                notification(response.error_description);
            }
            
        }else{
            snapr_user = username;
            access_token = response.access_token;
            $body.addClass('loggedin');
            update_mysnaps_link();
            store_user_credentials();

            // send data to iphone app
            if(appmode){
                pass_data('snapr://login?snapr_user='+username+'&access_token='+access_token);
            }
            if($.isFunction(callback)){
                callback();
            }else{
                close_overlay();
                //refresh()
                update_menu_activity_message();
                window.location.hash = add_extra_params(window.location.hash);
            }
        }
    });
}

function logout(){
    snapr_user = undefined;
    access_token = undefined;
    //refresh()
    $body.removeClass('loggedin');
    window.location.hash = add_extra_params('#'); 
    // send data to iphone app
    clear_user_credentials()
    if(appmode){
        pass_data('snapr://logout');
    }
}

function refresh(){
    abort_active_requests();
    $(window).trigger("hashchange", [true]);
}

jQuery.fn.jQmobile_enhance = function() {
$(this).find( "[data-role]" ).andSelf().each(function() {
        var $this = $( this ),
            role = $this.data( "role" );

        switch(role) {
            case "collapsible":
            case "fieldcontain":
            case "navbar":
            case "listview":
                $this[ role ]();
                break;
        }
    });

    var degradeInputs = {
        color: false,
        date: false,
        datetime: false,
        "datetime-local": false,
        email: false,
        month: false,
        number: false,
        range: "number",
        search: true,
        tel: false,
        time: false,
        url: false,
        week: false
    },
    keepNative = "[data-role='none'], [data-role='nojs']";

    // degrade inputs to avoid poorly implemented native functionality
    $(this).find( "input" ).not(keepNative).each(function() {
        var type = this.getAttribute( "type" ),
            optType = degradeInputs[ type ] || "text";

        if ( degradeInputs[ type ] ) {
            $( this ).replaceWith(
                $( "<div>" ).html( $(this).clone() ).html()
                    .replace( /type="([a-zA-Z]+)"/, "type="+ optType +" data-type='$1'" ) );
        }
    });

    // We re-find form elements since the degredation code above
    // may have injected new elements. We cache the non-native control
    // query to reduce the number of times we search through the entire page.

    var allControls = $(this).find("input, textarea, select, button"),
        nonNativeControls = allControls.not(keepNative);

    // XXX: Temporary workaround for issue 785. Turn off autocorrect and
    //      autocomplete since the popup they use can't be dismissed by
    //      the user. Note that we test for the presence of the feature
    //      by looking for the autocorrect property on the input element.

    var textInputs = allControls.filter( "input[type=text]" );
    if (textInputs.length && typeof textInputs[0].autocorrect !== "undefined") {
        textInputs.each(function(){
            // Set the attribute instead of the property just in case there
            // is code that attempts to make modifications via HTML.
            this.setAttribute("autocorrect", "off");
            this.setAttribute("autocomplete", "off");
        });
    }

    // enchance form controls
    nonNativeControls
        .filter( "[type='radio'], [type='checkbox']" )
        .checkboxradio();

    nonNativeControls
        .filter( "button, [type='button'], [type='submit'], [type='reset'], [type='image']" )
        .button();

    nonNativeControls
        .filter( "input, textarea" )
        .not( "[type='radio'], [type='checkbox'], [type='button'], [type='submit'], [type='reset'], [type='image'], [type='hidden']" )
        .textinput();

    nonNativeControls
        .filter( "input, select" )
        .filter( "[data-role='slider'], [data-type='range']" )
        .slider();

    nonNativeControls
        .filter( "select:not([data-role='slider'])" )
        .selectmenu();
};

function api_date(javascript_date) {
    //yyyy-MM-dd HH:mm:ss
    return $.PHPDate('Y-m-d H:i:s', javascript_date);
}

// like .data() but will not parse the value so the string "10E6" will not become 10000000
jQuery.fn.data2 = function( key ) {
    return this.attr('data-' + key);
};

jQuery.fn.prettyDate = function() {
    return this.each(function() {
        var $this = $(this);
        $this.text(prettyDate($this.data('date')));
    });
};

// short version
function prettyDate(time, relative){
    time = (time || "").replace(/-/g,"/").replace(/ \//g," -").replace(/[TZ]/g," ");
    //add 0000 to set to utc for relative times
    if(relative !== false && time.split(' ').length <3){
        time = time + ' -0000';
    }
    var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
    date = new Date(time),now = new Date(),
    diff = ((now.getTime() - date.getTime()) / 1000),
    day_diff = Math.floor(diff / 86400);
    date = new Date(time.replace(/ [\+-]\d{4}$/,'')); //strip TZ
    if(date.getHours() <= 12){
        var hours = date.getHours(),
        ap = 'AM'
    }else{
        var hours = date.getHours() -12,
        ap = 'PM'
    }
    if(relative !== false){
        if ( isNaN(day_diff) || day_diff < 0 )//|| day_diff >= 31 )
            return;
        if (day_diff == 0){
            return(
                diff < 60 && 'just now' ||
                diff < 3600 && Math.floor( diff / 60 ) + "min" ||
                diff < 86400 && Math.floor( diff / 3600 ) + "h ago"
            );
        }
        if (day_diff == 1){
            return 'Yesterday';
        }
        if (day_diff < 7){
            return day_diff + 'd ago';
        }
        if(date.getYear() == now.getYear()){
            return (date.getDate()).ordinal() + ' ' + months[date.getMonth()];
        }else{
            var yr = String(date.getFullYear());
            yr = yr.substring(yr.length - 2,yr.length);
            return (date.getDate()).ordinal() + ' ' + months[date.getMonth()] + ' \'' + yr;
        }
    }
    var full_date = hours+' '+ap+', '+months[date.getMonth()]+' '+date.getDate();
    if (date.getFullYear() == new Date().getFullYear())
        return full_date
    return full_date+', '+date.getFullYear()
}

function prettyLocation(txt){
    txt_array = txt.split(', ');
    new_txt_array = [];
    new_txt_array.push(txt_array[0]);
    if(txt_array.length > 1){
        if(txt_array[0].length + txt_array[1].length < 24){
            new_txt_array.push(txt_array[1]);
        }
    }
    return new_txt_array.join(', ');
}

// returns an empty string if not too old
// return "too-old" if the date is too old (more than one week old)
// date is a raw, unparsed string
// author: mike
function printTooOldClass(date) {
    var now = new Date().getTime();
    var prevDate = Date.parse(date);
    var oneWeek = 1000 * 60 * 60 * 24 * 7;
    var differenceSeconds = new Date(now - prevDate);
    if (differenceSeconds > oneWeek) {
        return 'too-old';
    } else {
        return '';
    }
}

Number.prototype.zeroFill = function( width ){
    width -= this.toString().length;
    if ( width > 0 )
    {
        return new Array( width + (/\./.test( this ) ? 2 : 1) ).join( '0' ) + this;
    }
    return this.toString();
}

Number.prototype.ordinal = function(){
    if( this!=11 && this!=12 && this!=13 ){
    that = String(this)
    switch( that.substr(that.length-1) ){
        case '1':
            return that+'st';
        case '2':
            return that+'nd';
        case '3':
            return that+'rd';
    }
    }
    return this+'th';
};

Array.prototype.remove =  function(thing){
    index = this.indexOf(thing);
    if(index != -1){
        this.splice(index,1);
    }
    return index;
};

Array.prototype.human_list =  function(){
    if(this.length==1){return this[0];}
    copy = this.slice(0);
    text = copy.pop();
    text = copy.pop() +' and '+ text;
    while(copy.length){
       text = copy.pop() +', '+ text; 
    }
    return text
};

function supports_local_storage() {
  try {
    return 'localStorage' in window && window['localStorage'] !== null;
  } catch (e) {
    return false;
  }
}


function convert_hash_tags_to_search_links(text) {
    return text.replace(
        /#([a-zA-Z0-9]+)/g,
        '<a class="hashtag" href="#feed.html?keywords=$1">#$1</a>'
    );
}


/* User settings local storage ************************************************/

/**
 * retuns the name of the current page minus the .html (eg: hotspots)
 */
function get_curr_page() {
    var s = window.location.hash.match(/#.+[.]/)[0];
    return s.substring(1, s.length - 1);
}

/**
 * saves the params for the current page to local storage
 */
function save_curr_params() {
    if (supports_local_storage()) {
        localStorage.setItem(get_curr_page(), JSON.stringify(params));
    }
}

function retrieve_saved_params() {
    if (supports_local_storage() && has_saved_params()) {
        params = JSON.parse(localStorage.getItem(get_curr_page()));
    }
}

/* just used for debugging */
function clear_saved_params() {
    if (supports_local_storage()) {
        localStorage.removeItem(get_curr_page());
    }
}

function has_saved_params(key) {
    if (supports_local_storage()) {
        if(key){
            var stored_data = localStorage.getItem(get_curr_page());
            if (stored_data == null) {
                //JSON.parse(null) will break android (just android :) ), so make sure this isnt' call
                return false;
            }
            var temp_params = JSON.parse(stored_data);
            return (temp_params && temp_params[key] != undefined)
        }else{
            return localStorage.getItem(get_curr_page()) != undefined;
        }
    } else {
        return false;
    }
}

/**
 * saves an assoc array to local storage to the variable with the name of the current page
 * @param settings  an associative array   (well, technically just an object, but really only meant for assoc array type objects)
 */
function save_curr_page_array(assoc_array) {
   if (supports_local_storage()) {
      if (supports_local_storage()) {
        localStorage.setItem(get_curr_page(), JSON.stringify(assoc_array));
     }
   }
}

/**
 * the array saved in local storage for the current page
 * @return an associative array (ok, object)
 */
function retreive_curr_page_array() {
    if (supports_local_storage() && has_saved_params()) {
        return JSON.parse(localStorage.getItem(get_curr_page()));
    } else {
        return {};
    }
}

function save_page_setting(name, value) {
    var settings = retreive_curr_page_array();
    settings[name] = value;
    save_curr_page_array(settings);
}

function delete_page_setting(name) {
    var settings = retreive_curr_page_array();
    delete settings[name];
    save_curr_page_array(settings);
}

function update_menu_activity_message() {
    if (snapr_user) {
        $.ajax({
            url: api_url+'/user/news/',
            dataType: 'jsonp',
            success: function(response){
                if(response.success){
                    var message = 'No news at the moment';
                    if (response.response.news.length) {
                        latest_news = response.response.news[0];
                        
                        if (latest_news.type == 'favorite') {
                              message = latest_news.user.username + ' liked your photo.'
                        }
                        else if (latest_news.type == 'comment') {
                            message = latest_news.user.username + ' commented on your photo.'
                        }
                        else if (latest_news.type == 'follow') {
                            message = latest_news.user.username + ' is now following you.'
                        }
                    }
                    $('.activity-message.user-only .txt').text(message);
                }else{
                    //notification(response.error.message);
                }
                spinner_stop();
            },
            error: function(request, status) {
                if(status != 'timeout') {
                    //notification("Application Error. Sorry!");
                } else {
                    // $('body').addClass('offline');
                }
            }
        });
    }
}

function back() {
    current_page.filename = current_page_filename();
    //console.log(current_page.filename);

    if (    (current_page.filename == 'my-account.html'
         || current_page.filename == 'linked-services.html'
         || current_page.filename == 'photo-edit.html'
         || current_page.filename == 'join-snapr-success.html')
         && (has_saved_params('back_url') || has_saved_params('redirect_url'))
    ){
        //console.log('special page');
        var stored_params = JSON.parse(localStorage.getItem(get_curr_page()));
        if(stored_params.redirect_url){
            delete_page_setting('redirect_url');
            window.location.href = add_extra_params(stored_params.redirect_url);
        }else if(stored_params.back_url){
            delete_page_setting('back_url');
            window.location.href = add_extra_params(stored_params.back_url);
        }
    } else if(params.redirect_url){
        //console.log('back using redirect url');
        window.location.href = unescape(params.redirect_url);
    } else if (params.back_url) {
        //console.log('back using back_url');
        window.location.href = unescape(params.back_url);
    } else {
        //console.log('back using history');
        history.back(1);
    }
}

function current_page_filename() {
    if (current_page.is_menu) {
        //console.log('is menu');
        return 'menu.html';
    } else {
        //console.log('hash:' + current_page.hash);
        var matches = current_page.hash.match(/#(.*.html)?.*/);
        //console.log(matches)
        return matches[1];
    }
}


function store_user_credentials() {
    if (supports_local_storage()) {
       localStorage.setItem('snapr_user', snapr_user);
       localStorage.setItem('access_token', access_token);
    } else {
        $.cookie('snapr_user', snapr_user);
        $.cookie('access_token', access_token);
    }
}

function retreive_user_credentials() {
    if (supports_local_storage()) {
        snapr_user = localStorage.getItem('snapr_user');
        access_token = localStorage.getItem('access_token');
    } else {
        snapr_user = $.cookie('snapr_user');
        access_token = $.cookie('access_token');
    }
}

function clear_user_credentials() {
    if (supports_local_storage()) {
        localStorage.clear('snapr_user');
        localStorage.clear('access_token');
    } else {
       $.cookie('snapr_user', null);
       $.cookie('access_token', null);
    }
}

/* based on http://stackoverflow.com/questions/948532/how-do-you-convert-a-javascript-date-to-utc */
Date.prototype.toUTCArray= function(){
    var D= this;
    var month = D.getUTCMonth();
    if (month < 9) {
        month = '0' + String(month + 1);
    } else{
        month = String(month + 1);
    }

    var date = D.getUTCDate();
    console.log(date);
    if (date < 10) {
        date = '0' + String(date);
    } else {
        date = String(date);
    }
    return {
        'year': String(D.getUTCFullYear()),
        'month': month,
        'date': date,
        'hours': String(D.getUTCHours()),
        'minutes': String(D.getUTCMinutes()),
        'seconds': String(D.getUTCSeconds())
    }
}
Date.prototype.toUTCApiDate= function(){
    var d = this.toUTCArray();
    return d.year + '-' + d.month + '-' + d.date + ' ' + d.hours + ':' + d.minutes + ':' + d.seconds
}


function update_mysnaps_link() {
    if (snapr_user) {
        $('#my-snaps').attr('href', '#feed.html?username='+snapr_user);
    }
}


