/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
function popWin(url, win, para) {
    var win = window.open(url, win, para);

    win.focus();
}

function setLocation(url) {
    window.location.href = url;
}

function setPLocation(url, setFocus) {
    if (setFocus) {
        window.opener.focus();
    }
    window.opener.location.href = url;
}

function setLanguageCode(code, fromCode) {
    //TODO: javascript cookies have different domain and path than php cookies
    var href = window.location.href;
    var after = '',
 dash;

    if (dash = href.match(/\#(.*)$/)) {
        href = href.replace(/\#(.*)$/, '');
        after = dash[0];
    }

    if (href.match(/[?]/)) {
        var re = /([?&]store=)[a-z0-9_]*/;

        if (href.match(re)) {
            href = href.replace(re, '$1' + code);
        } else {
            href += '&store=' + code;
        }

        var re = /([?&]from_store=)[a-z0-9_]*/;

        if (href.match(re)) {
            href = href.replace(re, '');
        }
    } else {
        href += '?store=' + code;
    }

    if (typeof fromCode != 'undefined') {
        href += '&from_store=' + fromCode;
    }
    href += after;

    setLocation(href);
}

/**
 * Add classes to specified elements.
 * Supported classes are: 'odd', 'even', 'first', 'last'
 *
 * @param elements - array of elements to be decorated
 * [@param decorateParams] - array of classes to be set. If omitted, all available will be used
 */
function decorateGeneric(elements, decorateParams) {
    var allSupportedParams = ['odd', 'even', 'first', 'last'];
    var _decorateParams = {};
    var total = elements.length;

    if (total) {
        // determine params called
        if (typeof decorateParams == 'undefined') {
            decorateParams = allSupportedParams;
        }

        if (!decorateParams.length) {
            return;
        }

        for (var k in allSupportedParams) {
            _decorateParams[allSupportedParams[k]] = false;
        }

        for (var k in decorateParams) {
            _decorateParams[decorateParams[k]] = true;
        }

        // decorate elements
        // elements[0].addClassName('first'); // will cause bug in IE (#5587)
        if (_decorateParams.first) {
            Element.addClassName(elements[0], 'first');
        }

        if (_decorateParams.last) {
            Element.addClassName(elements[total - 1], 'last');
        }

        for (var i = 0; i < total; i++) {
            if ((i + 1) % 2 == 0) {
                if (_decorateParams.even) {
                    Element.addClassName(elements[i], 'even');
                }
            } else if (_decorateParams.odd) {
                Element.addClassName(elements[i], 'odd');
            }
        }
    }
}

/**
 * Decorate table rows and cells, tbody etc
 * @see decorateGeneric()
 */
function decorateTable(table, options) {
    var table = $(table);

    if (table) {
        // set default options
        var _options = {
            'tbody': false,
            'tbody tr': ['odd', 'even', 'first', 'last'],
            'thead tr': ['first', 'last'],
            'tfoot tr': ['first', 'last'],
            'tr td': ['last']
        };
        // overload options

        if (typeof options != 'undefined') {
            for (var k in options) {
                _options[k] = options[k];
            }
        }
        // decorate
        if (_options['tbody']) {
            decorateGeneric(table.select('tbody'), _options['tbody']);
        }

        if (_options['tbody tr']) {
            decorateGeneric(table.select('tbody tr'), _options['tbody tr']);
        }

        if (_options['thead tr']) {
            decorateGeneric(table.select('thead tr'), _options['thead tr']);
        }

        if (_options['tfoot tr']) {
            decorateGeneric(table.select('tfoot tr'), _options['tfoot tr']);
        }

        if (_options['tr td']) {
            var allRows = table.select('tr');

            if (allRows.length) {
                for (var i = 0; i < allRows.length; i++) {
                    decorateGeneric(allRows[i].getElementsByTagName('TD'), _options['tr td']);
                }
            }
        }
    }
}

/**
 * Set "odd", "even" and "last" CSS classes for list items
 * @see decorateGeneric()
 */
function decorateList(list, nonRecursive) {
    if ($(list)) {
        if (typeof nonRecursive == 'undefined') {
            var items = $(list).select('li');
        } else {
            var items = $(list).childElements();
        }
        decorateGeneric(items, ['odd', 'even', 'last']);
    }
}

/**
 * Set "odd", "even" and "last" CSS classes for list items
 * @see decorateGeneric()
 */
function decorateDataList(list) {
    list = $(list);

    if (list) {
        decorateGeneric(list.select('dt'), ['odd', 'even', 'last']);
        decorateGeneric(list.select('dd'), ['odd', 'even', 'last']);
    }
}

/**
 * Parse SID and produces the correct URL
 */
function parseSidUrl(baseUrl, urlExt) {
    var sidPos = baseUrl.indexOf('/?SID=');
    var sid = '';

    urlExt = urlExt != undefined ? urlExt : '';

    if (sidPos > -1) {
        sid = '?' + baseUrl.substring(sidPos + 2);
        baseUrl = baseUrl.substring(0, sidPos + 1);
    }

    return baseUrl + urlExt + sid;
}

/**
 * Formats currency using patern
 * format - JSON (pattern, decimal, decimalsDelimeter, groupsDelimeter)
 * showPlus - true (always show '+'or '-'),
 *      false (never show '-' even if number is negative)
 *      null (show '-' if number is negative)
 */

function formatCurrency(price, format, showPlus) {
    var precision = isNaN(format.precision = Math.abs(format.precision)) ? 2 : format.precision;
    var requiredPrecision = isNaN(format.requiredPrecision = Math.abs(format.requiredPrecision)) ? 2 : format.requiredPrecision;

    //precision = (precision > requiredPrecision) ? precision : requiredPrecision;
    //for now we don't need this difference so precision is requiredPrecision
    precision = requiredPrecision;

    var integerRequired = isNaN(format.integerRequired = Math.abs(format.integerRequired)) ? 1 : format.integerRequired;

    var decimalSymbol = format.decimalSymbol == undefined ? ',' : format.decimalSymbol;
    var groupSymbol = format.groupSymbol == undefined ? '.' : format.groupSymbol;
    var groupLength = format.groupLength == undefined ? 3 : format.groupLength;

    var s = '';

    if (showPlus == undefined || showPlus == true) {
        s = price < 0 ? '-' :  showPlus ? '+' : '';
    } else if (showPlus == false) {
        s = '';
    }

    var i = parseInt(price = Math.abs(+price || 0).toFixed(precision)) + '';
    var pad = i.length < integerRequired ? integerRequired - i.length : 0;

    while (pad) {
        i = '0' + i; pad--;
    }
    j = (j = i.length) > groupLength ? j % groupLength : 0;
    re = new RegExp('(\\d{' + groupLength + '})(?=\\d)', 'g');

    /**
     * replace(/-/, 0) is only for fixing Safari bug which appears
     * when Math.abs(0).toFixed() executed on "0" number.
     * Result is "0.-0" :(
     */
    var r = (j ? i.substr(0, j) + groupSymbol : '') + i.substr(j).replace(re, '$1' + groupSymbol) + (precision ? decimalSymbol + Math.abs(price - i).toFixed(precision).replace(/-/, 0).slice(2) : '');
    var pattern = '';

    if (format.pattern.indexOf('{sign}') == -1) {
        pattern = s + format.pattern;
    } else {
        pattern = format.pattern.replace('{sign}', s);
    }

    return pattern.replace('%s', r).replace(/^\s\s*/, '').replace(/\s\s*$/, '');
}

function expandDetails(el, childClass) {
    if (Element.hasClassName(el, 'show-details')) {
        $$(childClass).each(function (item) {
            item.hide();
        });
        Element.removeClassName(el, 'show-details');
    } else {
        $$(childClass).each(function (item) {
            item.show();
        });
        Element.addClassName(el, 'show-details');
    }
}

// Version 1.0
var isIE = navigator.appVersion.match(/MSIE/) == 'MSIE';

if (!window.Varien)
    var Varien = new Object();

Varien.showLoading = function () {
    var loader = $('loading-process');

    loader && loader.show();
};
Varien.hideLoading = function () {
    var loader = $('loading-process');

    loader && loader.hide();
};
Varien.GlobalHandlers = {
    onCreate: function () {
        Varien.showLoading();
    },

    onComplete: function () {
        if (Ajax.activeRequestCount == 0) {
            Varien.hideLoading();
        }
    }
};

Ajax.Responders.register(Varien.GlobalHandlers);

/**
 * Quick Search form client model
 */
Varien.searchForm = Class.create();
Varien.searchForm.prototype = {
    initialize: function (form, field, emptyText) {
        this.form   = $(form);
        this.field  = $(field);
        this.emptyText = emptyText;

        Event.observe(this.form,  'submit', this.submit.bind(this));
        Event.observe(this.field, 'focus', this.focus.bind(this));
        Event.observe(this.field, 'blur', this.blur.bind(this));
        this.blur();
    },

    submit: function (event) {
        if (this.field.value == this.emptyText || this.field.value == '') {
            Event.stop(event);

            return false;
        }

        return true;
    },

    focus: function (event) {
        if (this.field.value == this.emptyText) {
            this.field.value = '';
        }

    },

    blur: function (event) {
        if (this.field.value == '') {
            this.field.value = this.emptyText;
        }
    }
};

Varien.DateElement = Class.create();
Varien.DateElement.prototype = {
    initialize: function (type, content, required, format) {
        if (type == 'id') {
            // id prefix
            this.day    = $(content + 'day');
            this.month  = $(content + 'month');
            this.year   = $(content + 'year');
            this.full   = $(content + 'full');
            this.advice = $(content + 'date-advice');
        } else if (type == 'container') {
            // content must be container with data
            this.day    = content.day;
            this.month  = content.month;
            this.year   = content.year;
            this.full   = content.full;
            this.advice = content.advice;
        } else {
            return;
        }

        this.required = required;
        this.format   = format;

        this.day.addClassName('validate-custom');
        this.day.validate = this.validate.bind(this);
        this.month.addClassName('validate-custom');
        this.month.validate = this.validate.bind(this);
        this.year.addClassName('validate-custom');
        this.year.validate = this.validate.bind(this);

        this.setDateRange(false, false);
        this.year.setAttribute('autocomplete', 'off');

        this.advice.hide();
    },
    validate: function () {
        var error = false,
            day   = parseInt(this.day.value, 10)   || 0,
            month = parseInt(this.month.value, 10) || 0,
            year  = parseInt(this.year.value, 10)  || 0;

        if (this.day.value.strip().empty() &&
            this.month.value.strip().empty() &&
            this.year.value.strip().empty()
        ) {
            if (this.required) {
                error = 'Please enter a date.';
            } else {
                this.full.value = '';
            }
        } else if (!day || !month || !year) {
            error = 'Please enter a valid full date.';
        } else {
            var date = new Date,
 countDaysInMonth = 0,
 errorType = null;

            date.setYear(year); date.setMonth(month - 1); date.setDate(32);
            countDaysInMonth = 32 - date.getDate();

            if (!countDaysInMonth || countDaysInMonth > 31) countDaysInMonth = 31;

            if (day < 1 || day > countDaysInMonth) {
                errorType = 'day';
                error = 'Please enter a valid day (1-%1).';
            } else if (month < 1 || month > 12) {
                errorType = 'month';
                error = 'Please enter a valid month (1-12).';
            } else {
                if (day % 10 == day) this.day.value = '0' + day;

                if (month % 10 == month) this.month.value = '0' + month;
                this.full.value = this.format.replace(/%[mb]/i, this.month.value).replace(/%[de]/i, this.day.value).replace(/%y/i, this.year.value);
                var testFull = this.month.value + '/' + this.day.value + '/' + this.year.value;
                var test = new Date(testFull);

                if (isNaN(test)) {
                    error = 'Please enter a valid date.';
                } else {
                    this.setFullDate(test);
                }
            }
            var valueError = false;

            if (!error && !this.validateData()) {//(year<1900 || year>curyear) {
                errorType = this.validateDataErrorType;//'year';
                valueError = this.validateDataErrorText;//'Please enter a valid year (1900-%d).';
                error = valueError;
            }
        }

        if (error !== false) {
            if (jQuery.mage.__) {
                error = jQuery.mage.__(error);
            }

            if (!valueError) {
                this.advice.innerHTML = error.replace('%1', countDaysInMonth);
            } else {
                this.advice.innerHTML = this.errorTextModifier(error);
            }
            this.advice.show();

            return false;
        }

        // fixing elements class
        this.day.removeClassName('validation-failed');
        this.month.removeClassName('validation-failed');
        this.year.removeClassName('validation-failed');

        this.advice.hide();

        return true;
    },
    validateData: function () {
        var year = this.fullDate.getFullYear();
        var date = new Date;

        this.curyear = date.getFullYear();

        return year >= 1900 && year <= this.curyear;
    },
    validateDataErrorType: 'year',
    validateDataErrorText: 'Please enter a valid year (1900-%1).',
    errorTextModifier: function (text) {
        return text.replace('%1', this.curyear);
    },
    setDateRange: function (minDate, maxDate) {
        this.minDate = minDate;
        this.maxDate = maxDate;
    },
    setFullDate: function (date) {
        this.fullDate = date;
    }
};

Varien.DOB = Class.create();
Varien.DOB.prototype = {
    initialize: function (selector, required, format) {
        var el = $$(selector)[0];
        var container       = {};

        container.day       = Element.select(el, '.dob-day input')[0];
        container.month     = Element.select(el, '.dob-month input')[0];
        container.year      = Element.select(el, '.dob-year input')[0];
        container.full      = Element.select(el, '.dob-full input')[0];
        container.advice    = Element.select(el, '.validation-advice')[0];

        new Varien.DateElement('container', container, required, format);
    }
};

Varien.dateRangeDate = Class.create();
Varien.dateRangeDate.prototype = Object.extend(new Varien.DateElement(), {
    validateData: function () {
        var validate = true;

        if (this.minDate || this.maxValue) {
            if (this.minDate) {
                this.minDate = new Date(this.minDate);
                this.minDate.setHours(0);

                if (isNaN(this.minDate)) {
                    this.minDate = new Date('1/1/1900');
                }
                validate = validate && this.fullDate >= this.minDate;
            }

            if (this.maxDate) {
                this.maxDate = new Date(this.maxDate);
                this.minDate.setHours(0);

                if (isNaN(this.maxDate)) {
                    this.maxDate = new Date();
                }
                validate = validate && this.fullDate <= this.maxDate;
            }

            if (this.maxDate && this.minDate) {
                this.validateDataErrorText = 'Please enter a valid date between %s and %s';
            } else if (this.maxDate) {
                this.validateDataErrorText = 'Please enter a valid date less than or equal to %s';
            } else if (this.minDate) {
                this.validateDataErrorText = 'Please enter a valid date equal to or greater than %s';
            } else {
                this.validateDataErrorText = '';
            }
        }

        return validate;
    },
    validateDataErrorText: 'Date should be between %s and %s',
    errorTextModifier: function (text) {
        if (this.minDate) {
            text = text.sub('%s', this.dateFormat(this.minDate));
        }

        if (this.maxDate) {
            text = text.sub('%s', this.dateFormat(this.maxDate));
        }

        return text;
    },
    dateFormat: function (date) {
        return date.getMonth() + 1 + '/' + date.getDate() + '/' + date.getFullYear();
    }
});

Varien.FileElement = Class.create();
Varien.FileElement.prototype = {
    initialize: function (id) {
        this.fileElement = $(id);
        this.hiddenElement = $(id + '_value');

        this.fileElement.observe('change', this.selectFile.bind(this));
    },
    selectFile: function (event) {
        this.hiddenElement.value = this.fileElement.getValue();
    }
};

Validation.addAllThese([
    ['validate-custom', ' ', function (v, elm) {
        return elm.validate();
    }]
]);

Element.addMethods({
    getInnerText: function (element) {
        element = $(element);

        if (element.innerText && !Prototype.Browser.Opera) {
            return element.innerText;
        }

        return element.innerHTML.stripScripts().unescapeHTML().replace(/[\n\r\s]+/g, ' ').strip();
    }
});

/*
if (!("console" in window) || !("firebug" in console))
{
    var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
    "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];

    window.console = {};
    for (var i = 0; i < names.length; ++i)
        window.console[names[i]] = function() {}
}
*/

/**
 * Executes event handler on the element. Works with event handlers attached by Prototype,
 * in a browser-agnostic fashion.
 * @param element The element object
 * @param event Event name, like 'change'
 *
 * @example fireEvent($('my-input', 'click'));
 */
function fireEvent(element, event) {
    // dispatch event
    var evt = document.createEvent('HTMLEvents');

    evt.initEvent(event, true, true); // event type, bubbling, cancelable
    return element.dispatchEvent(evt);

}

/**
 * Returns more accurate results of floating-point modulo division
 * E.g.:
 * 0.6 % 0.2 = 0.19999999999999996
 * modulo(0.6, 0.2) = 0
 *
 * @param dividend
 * @param divisor
 */
function modulo(dividend, divisor) {
    var epsilon = divisor / 10000;
    var remainder = dividend % divisor;

    if (Math.abs(remainder - divisor) < epsilon || Math.abs(remainder) < epsilon) {
        remainder = 0;
    }

    return remainder;
}

/**
 * createContextualFragment is not supported in IE9. Adding its support.
 */
if (typeof Range != 'undefined' && !Range.prototype.createContextualFragment) {
    Range.prototype.createContextualFragment = function (html) {
        var frag = document.createDocumentFragment(),
        div = document.createElement('div');

        frag.appendChild(div);
        div.outerHTML = html;

        return frag;
    };
}

/**
 * Convert byte count to float KB/MB format
 *
 * @param int $bytes
 * @return string
 */
var byteConvert = function (bytes) {
    if (isNaN(bytes)) {
        return '';
    }
    var symbols = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
    var exp = Math.floor(Math.log(bytes) / Math.log(2));

    if (exp < 1) {
        exp = 0;
    }
    var i = Math.floor(exp / 10);

    bytes /= Math.pow(2, 10 * i);

    if (bytes.toString().length > bytes.toFixed(2).toString().length) {
        bytes = bytes.toFixed(2);
    }

    return bytes + ' ' + symbols[i];
};
