/**
 * app.util_b.js
 * JavaScript browser utilities
 *
 */

/*jslint         browser : true, continue : true,
  devel  : true, indent  : 2,    maxerr   : 50,
  newcap : true, nomen   : true, plusplus : true,
  regexp : true, sloppy  : true, vars     : false,
  white  : true
*/
/*global $, app, getComputedStyle */

app.util_b = (function() {
    'use strict';
    //---------------- BEGIN MODULE SCOPE VARIABLES --------------
    var
        configMap = {
            regex_encode_html: /[&"'><]/g,
            regex_encode_noamp: /["'><]/g,
            html_encode_map: {
                '&': '&#38;',
                '"': '&#34;',
                "'": '&#39;',
                '>': '&#62;',
                '<': '&#60;'
            }
        },

        decodeHtml, encodeHtml, getEmSize, getApiUrl, getUrlParams, formData, objectifyFormDataArray,
        getMediaSize, prepareObjectForClient, fixDatesToStrings, utcStringToShortDate, genListColumn,
        autoComplete;

    configMap.encode_noamp_map = $.extend({}, configMap.html_encode_map);
    delete configMap.encode_noamp_map['&'];
    //----------------- END MODULE SCOPE VARIABLES ---------------

    //------------------- BEGIN UTILITY METHODS ------------------


    // Begin decodeHtml
    // Decodes HTML entities in a browser-friendly way
    // See http://stackoverflow.com/questions/1912501/\
    //   unescape-html-entities-in-javascript
    //
    decodeHtml = function(str) {
        return $('<div/>').html(str || '').text();
    };
    // End decodeHtml


    // Begin encodeHtml
    // This is single pass encoder for html entities and handles
    // an arbitrary number of characters
    //
    encodeHtml = function(input_arg_str, exclude_amp) {
        var
            input_str = String(input_arg_str),
            regex, lookup_map;

        if (exclude_amp) {
            lookup_map = configMap.encode_noamp_map;
            regex = configMap.regex_encode_noamp;
        } else {
            lookup_map = configMap.html_encode_map;
            regex = configMap.regex_encode_html;
        }
        return input_str.replace(regex,
            function(match, name) {
                return lookup_map[match] || '';
            }
        );
    };
    // End encodeHtml

    // Begin getEmSize
    // returns size of ems in pixels
    //
    getEmSize = function(elem) {
        return Number(
            getComputedStyle(elem, '').fontSize.match(/\d*\.?\d*/)[0]
        );
    };
    // End getEmSize


    //Begin getApiUrl
    //returns url for api methods by parsing current window location url
    //
    getApiUrl = function() {
        var u = window.location.href.replace(window.location.hash, "").replace('app.html', '') + "api/";
        //is it a dev local url?
        if (u.indexOf("localhost:8080") != -1) {
            u = u.replace("8080", "8081");
        }
        // End getApiUrl

        //fix for random recurrence of extraneous ? on iPhone when using api
        //(Cannot post to http://gl-gztw.rhcloud.com/?api/list (404))
        u = u.replace("?", "");

        return u;
    }





    // Begin formData
    // Get or set all form fields
    //
    formData = function(data) {

        //fix dates into strings
        prepareObjectForClient(data);


        var inps = $(":input").get();

        if (typeof data != "object") {
            // return all data
            data = {};

            $.each(inps, function() {
                if (this.name && (this.checked || /select|textarea/i.test(this.nodeName) || /text|hidden|password/i.test(this.type))) {
                    data[this.name] = $(this).val();
                }
            });
            return data;
        } else {
            $.each(inps, function() {
                if (this.name && data[this.name]) {
                    if (this.type == "checkbox" || this.type == "radio") {
                        $(this).prop("checked", (data[this.name]));
                    } else {
                        $(this).val(data[this.name]);
                    }
                } else if (this.type == "checkbox") {
                    $(this).prop("checked", false);
                }
            });
            return $(this);
        }
    };
    // End formdata

    // Begin getMediaSize
    // Retrieves results of css media query in hidden pseudo element
    // :after body element
    //objectifyFormDataArray
    getMediaSize = function() {
        return window.getComputedStyle(document.querySelector('body'), ':after').getPropertyValue('content').replace(/\"/g, '');
    };
    // End getMediaSize





    //Begin objectifyFormDataArray
    //takes name value form input pairs in array and turns into a keyed object
    //suitable for sending as json object
    //
    objectifyFormDataArray = function(arr) {
        var rv = {};
        for (var i = 0; i < arr.length; ++i)
            if (arr[i] !== undefined) rv[arr[i].name] = arr[i].value;
        return rv;
    }



    //This function exists to change the properties of the passed in object
    //to values compatible with jquery form filling functions (mostly dates to strings for now)
    //
    prepareObjectForClient = function(obj) {
            if (Array.isArray(obj)) {
                for (var i = 0; i < obj.length; i++) {
                    fixDatesToStrings(obj[i]);
                }
            } else {
                fixDatesToStrings(obj);
            }
            return obj;
        }
        //

    //Turn date fields of object coming from db into stringified values for consumption by client
    //turn null dates into empty strings and iso date values into strings in iso format
    fixDatesToStrings = function(obj) {
            var keys = Object.keys(obj);
            keys.forEach(function(key) {
                if (key.endsWith('Date')) {
                    var value = obj[key];
                    if (value == null) {
                        obj[key] = '';
                    } else {
                        //for some reason they come to us as a string, not a date so just chop off the 
                        //extraneous bits as it's a standard iso string
                        obj[key] = value.substring(0, 10);
                    }
                }
            });
        }
        //

    //Turn date strings coming in as utc from server into displayable short date format
    //
    utcStringToShortDate = function(strDate) {
            if (strDate == null) return '';
            //ensure there is something there
            if (strDate.length > 10) {
                return strDate.substring(0, 10);
            }

            //bugbug: this won't work because date comes in UTC from db and the first line converts to local time
            // var d = new Date(strDate),
            //     month = '' + (d.getMonth() + 1),
            //     day = '' + d.getDate(),
            //     year = d.getFullYear();

            // if (month.length < 2) month = '0' + month;
            // if (day.length < 2) day = '0' + day;

            // return [year, month, day].join('-');
        }
        //


    // Begin genListColumn
    // This function is used to demarcate 'columns' of fields in basic list forms by wrapping each column field in html
    //
    genListColumn = function(val) {
        return '<span class="app-list-column">' + val + '</span>'
    };
    // End genListColumn


    // Begin autoComplete
    // This function is used to attach an autocomplete method to an input
    //
    autoComplete = function(controlId, acGetToken) {
        $('#' + controlId).autocomplete({
            serviceUrl: app.shell.stateMap.apiUrl + 'autocomplete',
            params: {
                acget: acGetToken
            },
            ajaxSettings: {
                headers: {
                    'x-access-token': app.shell.stateMap.user.token
                }
            }
        });
    };
    // End autoComplete



    // export methods
    return {
        decodeHtml: decodeHtml,
        encodeHtml: encodeHtml,
        getEmSize: getEmSize,
        getApiUrl: getApiUrl,
        getUrlParams: getUrlParams,
        formData: formData,
        getMediaSize: getMediaSize,
        objectifyFormDataArray: objectifyFormDataArray,
        utcStringToShortDate: utcStringToShortDate,
        genListColumn: genListColumn,
        autoComplete:autoComplete
    };
    //------------------- END PUBLIC METHODS ---------------------
}());