"use strict";

/*jslint white: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: false,
bitwise: true, regexp: true, strict: true, newcap: true, immed: true */

/*global dojo */

/**
 * interact with PHP and create graphical button replacements 
 * @constructor
 * @author milodorn
 * @version 1.0
 */
function CFGraphicalButtons() {
    
    var THIS = this;
    
    /**
     * class name prefix for 'auto' button type
     * @memberOf CFGraphicalButtons
     * @type String
     * @return {String}
     */
    this.autoClassName = 'cf-button-';
    
    /**
     * class name prefix for 'auto' mouse over button type
     * @memberOf CFGraphicalButtons
     * @type String
     * @return {String}
     */
    this.autoClassOverName = 'cf-button_over-';
    
    /**
     * button type - currently allowed types are 'auto', 'gray', 'blue', 'green', 'orange'
     * @memberOf CFGraphicalButtons
     * @type String
     * @return {String}
     */
    this.buttonType = 'auto';

    /**
     * mouse over button type, use 'none' for no mouseover effect
     * @memberOf CFGraphicalButtons
     * @type String
     * @return {String}
     */
    this.buttonOverType = 'none';

    /**
     * path to php button creator file directory
     * @memberOf CFGraphicalButtons
     * @type String
     * @return {String}
     */
    this.phpPath = '../php';

    /**
     * php creator file name
     * @memberOf CFGraphicalButtons
     * @type String
     * @return {String}
     */
    this.phpButton = 'graphicalbutton.php?tp=%%%type%%%&w=%%%width%%%';

    /**
     * create graphical button from INPUT element
     * @memberOf CFGraphicalButtons
     * @type Function
     * @return {undefined}
     * @param {HTMLElement} el
     */
    this.createButtonFromInput = function (el) {
        var it;  // input type value
        
        // allow only 'submit' or 'button' types
        it = dojo.attr(el, 'type');
        if ((it !== 'submit') && (it !== 'button')) {
            return;
        }
        // create button
        THIS.createButtonFromLink(el);
    };
    
    /**
     * create graphical button from A element
     * @memberOf CFGraphicalButtons
     * @type Function
     * @return {undefined}
     * @param {HTMLElement} el
     */
    this.createButtonFromLink = function (el) {
        var btp, // button type
        btpo, // button mouse over type
        elp, // element for image preload
        width; // computed button width

        // create button
        btp = THIS.buttonType === 'auto' ? THIS.getTypeFromClassName(el) : THIS.buttonType;
        btpo = THIS.buttonOverType === 'none' ? 'auto' : (THIS.buttonOverType === 'auto' ?
            THIS.getTypeFromClassName(el, true) : THIS.buttonOverType);
        el.style.border = 0;
        width = THIS.getElementWidth(el);
        // cache button
        elp = dojo.create('img', {src: THIS.getButtonUri(btp, width)}, el.parentNode, el);
        elp.style.position = 'absolute';
        elp.style.left = '-15000px';
        // set button
        el.style.background = 'transparent url("' + THIS.getButtonUri(btp, width) +
            '") 0 0 no-repeat';
        if (btpo !== 'auto') {
            // cache mouseover button
            elp = dojo.create('img', {src: THIS.getButtonUri(btpo, width)}, el.parentNode, el);
            elp.style.position = 'absolute';
            elp.style.left = '-15000px';
            // store over/out states
            el.cfbgBtp = 'transparent url("' + THIS.getButtonUri(btp, width) + '") 0 0 no-repeat';
            el.cfbgBtpo = 'transparent url("' + THIS.getButtonUri(btpo, width) + '") 0 0 no-repeat';
            // set mousever button actions
            el.onmouseover = function () {
                this.style.background = this.cfbgBtpo;
            };
            el.onmouseout = function () {
                this.style.background = this.cfbgBtp;
            };
        }
    };
    
    /**
     * compose path to button URI
     * @memberOf CFGraphicalButtons
     * @type Function
     * @return {String}
     * @param {String} type
     * @param {Number} width
     */
    this.getButtonUri = function (type, width) {
        return THIS.phpPath + THIS.phpButton.replace('%%%type%%%', String(type)).
            replace('%%%width%%%', Number(width));
    };
    
    /**
     * compute element's real width
     * @memberOf CFGraphicalButtons
     * @type Function
     * @return {Number}
     * @param {HTMLElement} el
     */
    this.getElementWidth = function (el) {
        var coords, // object coordinates and size
        wdelta, // width delta 
        mbck; // stored margin value

        mbck = el.style.margin;
        coords = dojo.coords(el);
        wdelta = coords.w;
        el.style.margin = 0;
        coords = dojo.coords(el);
        wdelta -= coords.w;
        el.style.margin = mbck;
        return coords.w - wdelta;
    };
    
    /**
     * read element class names and find button type if available 
     * @memberOf CFGraphicalButtons
     * @type Function
     * @return {undefined}
     * @param {HTMLElement} el
     * @param {Boolean} over
     */
    this.getTypeFromClassName = function (el, over) {
        var acn, // auto-class name prefix
        acnl, // auto-class name prefix length
        cn, // class name string
        cna, // class array
        def, // default button type
        i; // iterator
        
        cn = el.className;
        if (typeof cn === 'string') {
            def = over ? 'auto' : 'gray';
            cna = cn.split(' ');
            acn = over ? THIS.autoClassOverName : THIS.autoClassName;
            acnl = acn.length;
            i = 0;
            while (i < cna.length) {
                if (cna[i].substr(0, acnl) === acn) {
                    return cna[i].substr(acnl); 
                }
                i++;
            }
        }
        return def;
    };
        
    /**
     * main function for button replacement
     * @memberOf CFGraphicalButtons
     * @type Function
     * @return {undefined} 
     * @param {String} dojoQuery
     */
    this.makeButtons = function (dojoQuery) {
        THIS.refreshButtons(dojo.query(dojoQuery));
    };
    
    /**
     * main function for button replacement
     * @memberOf CFGraphicalButtons
     * @type Function
     * @return {undefined} 
     * @param {Array} bEls
     */
    this.refreshButtons = function (bEls) {
        if (dojo.isArray(bEls)) {
            dojo.forEach(bEls, function (item) {
                var tn; // current element tag name
                
                tn = item.tagName.toLowerCase();
                if (tn === 'a') { // make button from link
                    THIS.createButtonFromLink(item);
                } else if (tn === 'input') { // make button from INPUT
                    THIS.createButtonFromInput(item);
                }
            });
        }
    };
}