if (window.ice && window.ice.icepush) {
    (function(namespace) {
function apply(fun, arguments) {
    return fun.apply(fun, arguments);
}
function withArguments() {
    var args = arguments;
    return function(fun) {
        apply(fun, args);
    };
}
function let(definition) {
    return function() {
        return apply(definition, arguments);
    };
}
function curry() {
    var args = arguments;
    return function() {
        var curriedArguments = [];
        var fun = args[0];
        for (var i = 1; i < args.length; i++) curriedArguments.push(args[i]);
        for (var j = 0; j < arguments.length; j++) curriedArguments.push(arguments[j]);
        return apply(fun, curriedArguments);
    };
}
function $witch(tests, defaultRun) {
    return function(val) {
        var args = arguments;
        var conditions = [];
        var runs = [];
        tests(function(condition, run) {
            conditions.push(condition);
            runs.push(run);
        });
        var size = conditions.length;
        for (var i = 0; i < size; i++) {
            if (apply(conditions[i], args)) {
                return apply(runs[i], args);
            }
        }
        if (defaultRun) apply(defaultRun, args);
    };
}
function identity(arg) {
    return arg;
}
function negate(b) {
    return !b;
}
function greater(a, b) {
    return a > b;
}
function less(a, b) {
    return a < b;
}
function not(a) {
    return !a;
}
function multiply(a, b) {
    return a * b;
}
function plus(a, b) {
    return a + b;
}
function max(a, b) {
    return a > b ? a : b;
}
function increment(value, step) {
    return value + (step ? step : 1);
}
function decrement(value, step) {
    return value - (step ? step : 1);
}
function any() {
    return true;
}
function none() {
    return false;
}
function noop() {
}
function isArray(a) {
    return a && !!a.push;
}
function isString(s) {
    return typeof s == 'string';
}
function isNumber(s) {
    return typeof s == 'number';
}
function isBoolean(s) {
    return typeof s == 'boolean';
}
function isIndexed(s) {
    return typeof s.length == 'number';
}
function isObject(o) {
    return o.instanceTag == o;
}
var uid = (function() {
    var id = 0;
    return function() {
        return id++;
    };
})();
function operationNotSupported() {
    throw 'operation not supported';
}
function operator(defaultOperation) {
    return function() {
        var args = arguments;
        var instance = arguments[0];
        if (instance.instanceTag && instance.instanceTag == instance) {
            var method = instance(arguments.callee);
            if (method) {
                return method.apply(method, args);
            } else {
                operationNotSupported();
            }
        } else {
            return defaultOperation ? defaultOperation.apply(defaultOperation, args) : operationNotSupported();
        }
    };
}
var asString = operator(String);
var asNumber = operator(Number);
var hash = operator(function(o) {
    var s;
    if (isString(o)) {
        s = o;
    } else if (isNumber(o)) {
        return Math.abs(Math.round(o));
    } else {
        s = o.toString();
    }
    var h = 0;
    for (var i = 0, l = s.length; i < l; i++) {
        var c = parseInt(s[i], 36);
        if (!isNaN(c)) {
            h = c + (h << 6) + (h << 16) - h;
        }
    }
    return Math.abs(h);
});
var equal = operator(function(a, b) {
    return a == b;
});
function object(definition) {
    var operators = [];
    var methods = [];
    var unknown = null;
    var id = uid();
    operators.push(hash);
    methods.push(function(self) {
        return id;
    });
    operators.push(equal);
    methods.push(function(self, other) {
        return self == other;
    });
    operators.push(asString);
    methods.push(function(self) {
        return 'Object:' + id.toString(16);
    });
    definition(function(operator, method) {
        var size = operators.length;
        for (var i = 0; i < size; i++) {
            if (operators[i] == operator) {
                methods[i] = method;
                return;
            }
        }
        operators.push(operator);
        methods.push(method);
    }, function(method) {
        unknown = method;
    });
    function self(operator) {
        var size = operators.length;
        for (var i = 0; i < size; i++) {
            if (operators[i] == operator) {
                return methods[i];
            }
        }
        return unknown;
    }
    return self.instanceTag = self;
}
function objectWithAncestors() {
    var definition = arguments[0];
    var args = arguments;
    var o = object(definition);
    function self(operator) {
        var method = o(operator);
        if (method) {
            return method;
        } else {
            var size = args.length;
            for (var i = 1; i < size; i++) {
                var ancestor = args[i];
                var overriddenMethod = ancestor(operator);
                if (overriddenMethod) {
                    return overriddenMethod;
                }
            }
            return null;
        }
    }
    return self.instanceTag = self;
}
var indexOf = operator($witch(function(condition) {
    condition(isString, function(items, item) {
        return items.indexOf(item);
    });
    condition(isArray, function(items, item) {
        for (var i = 0, size = items.length; i < size; i++) {
            if (items[i] == item) {
                return i;
            }
        }
        return -1;
    });
    condition(any, operationNotSupported);
}));
var concatenate = operator(function(items, other) {
    return items.concat(other);
});
var append = operator(function(items, item) {
    if (isArray(items)) {
        items.push(item);
        return items;
    } else {
        operationNotSupported();
    }
});
var insert = operator($witch(function(condition) {
    condition(isArray, function(items, item) {
        items.unshift(item);
        return items;
    });
    condition(any, operationNotSupported);
}));
var each = operator(function(items, iterator) {
    var size = items.length;
    for (var i = 0; i < size; i++) iterator(items[i], i);
});
var inject = operator(function(items, initialValue, injector) {
    var tally = initialValue;
    var size = items.length;
    for (var i = 0; i < size; i++) {
        tally = injector(tally, items[i]);
    }
    return tally;
});
var select = operator($witch(function(condition) {
    condition(isArray, function(items, selector) {
        return inject(items, [], function(tally, item) {
            return selector(item) ? append(tally, item) : tally;
        });
    });
    condition(isString, function(items, selector) {
        return inject(items, '', function(tally, item) {
            return selector(item) ? concatenate(tally, item) : tally;
        });
    });
    condition(isIndexed, function(items, selector) {
        return Stream(function(cellConstructor) {
            function selectingStream(start, end) {
                if (start > end) return null;
                var item = items[start];
                return selector(item) ?
                       function() {
                           return cellConstructor(item, selectingStream(start + 1, end));
                       } : selectingStream(start + 1, end);
            }
            return selectingStream(0, items.length - 1);
        });
    });
}));
var detect = operator(function(items, iterator, notDetectedThunk) {
    var size = items.length;
    for (var i = 0; i < size; i++) {
        var element = items[i];
        if (iterator(element, i)) {
            return element;
        }
    }
    return notDetectedThunk ? notDetectedThunk(items) : null;
});
var contains = operator($witch(function(condition) {
    condition(isString, function(items, item) {
        return items.indexOf(item) > -1;
    });
    condition(isArray, function(items, item) {
        var size = items.length;
        for (var i = 0; i < size; i++) {
            if (items[i] == item) {
                return true;
            }
        }
        return false;
    });
    condition(any, operationNotSupported);
}));
var size = operator(function(items) {
    return items.length;
});
var empty = operator(function(items) {
    items.length = 0;
});
var isEmpty = operator(function(items) {
    return items.length == 0;
});
var notEmpty = function(items) {
    return !isEmpty(items);
};
var collect = operator($witch(function(condition) {
    condition(isString, function(items, collector) {
        return inject(items, '', function(tally, item) {
            return concatenate(tally, collector(item));
        });
    });
    condition(isArray, function(items, collector) {
        return inject(items, [], function(tally, item) {
            return append(tally, collector(item));
        });
    });
    condition(isIndexed, function(items, collector) {
        return Stream(function(cellConstructor) {
            function collectingStream(start, end) {
                if (start > end) return null;
                return function() {
                    return cellConstructor(collector(items[start], start), collectingStream(start + 1, end));
                };
            }
            return collectingStream(0, items.length - 1);
        });
    });
}));
var sort = operator(function(items, sorter) {
    return copy(items).sort(function(a, b) {
        return sorter(a, b) ? -1 : 1;
    });
});
var reverse = operator(function(items) {
    return copy(items).reverse();
});
var copy = operator(function(items) {
    return inject(items, [], curry(append));
});
var join = operator(function(items, separator) {
    return items.join(separator);
});
var inspect = operator();
var reject = function(items, rejector) {
    return select(items, function(i) {
        return !rejector(i);
    });
};
var intersect = operator(function(items, other) {
    return select(items, curry(contains, other));
});
var complement = operator(function(items, other) {
    return reject(items, curry(contains, other));
});
var broadcast = function(items, args) {
    args = args || [];
    each(items, function(i) {
        apply(i, args);
    });
};
var broadcaster = function(items) {
    return function() {
        var args = arguments;
        each(items, function(i) {
            apply(i, args);
        });
    };
};
var asArray = function(items) {
    return inject(items, [], append);
};
var asSet = function(items) {
    return inject(items, [], function(set, item) {
        if (not(contains(set, item))) {
            append(set, item);
        }
        return set;
    });
};
var key = operator();
var value = operator();
function Cell(k, v) {
    return object(function(method) {
        method(key, function(self) {
            return k;
        });
        method(value, function(self) {
            return v;
        });
        method(asString, function(self) {
            return 'Cell[' + asString(k) + ': ' + asString(v) + ']';
        });
    });
}
function Stream(streamDefinition) {
    var stream = streamDefinition(Cell);
    return object(function(method) {
        method(each, function(self, iterator) {
            var cursor = stream;
            while (cursor != null) {
                var cell = cursor();
                iterator(key(cell));
                cursor = value(cell);
            }
        });
        method(inject, function(self, initialValue, injector) {
            var tally = initialValue;
            var cursor = stream;
            while (cursor != null) {
                var cell = cursor();
                tally = injector(tally, key(cell));
                cursor = value(cell);
            }
            return tally;
        });
        method(join, function(self, separator) {
            var tally;
            var cursor = stream;
            while (cursor != null) {
                var cell = cursor();
                var itemAsString = asString(key(cell));
                tally = tally ? tally + separator + itemAsString : itemAsString;
                cursor = value(cell);
            }
            return tally;
        });
        method(collect, function(self, collector) {
            return Stream(function(cellConstructor) {
                function collectingStream(stream) {
                    if (!stream) return null;
                    var cell = stream();
                    return function() {
                        return cellConstructor(collector(key(cell)), collectingStream(value(cell)));
                    };
                }
                return collectingStream(stream);
            });
        });
        method(contains, function(self, item) {
            var cursor = stream;
            while (cursor != null) {
                var cell = cursor();
                if (item == key(cell)) return true;
                cursor = value(cell);
            }
            return false;
        });
        method(size, function(self) {
            var cursor = stream;
            var i = 0;
            while (cursor != null) {
                i++;
                cursor = value(cursor());
            }
            return i;
        });
        method(select, function(self, selector) {
            return Stream(function(cellConstructor) {
                function select(stream) {
                    if (!stream) return null;
                    var cell = stream();
                    var k = key(cell);
                    var v = value(cell);
                    return selector(k) ? function() {
                        return cellConstructor(k, select(v));
                    } : select(v);
                }
                return select(stream);
            });
        });
        method(detect, function(self, detector, notDetectedThunk) {
            var cursor = stream;
            var result;
            while (cursor != null) {
                var cell = cursor();
                var k = key(cell);
                if (detector(k)) {
                    result = k;
                    break;
                }
                cursor = value(cell);
            }
            if (result) {
                return result;
            } else {
                return notDetectedThunk ? notDetectedThunk(self) : null;
            }
        });
        method(isEmpty, function(self) {
            return stream == null;
        });
        method(copy, function(self) {
            return Stream(streamDefinition);
        });
        method(asString, function(self) {
            return 'Stream[' + join(self, ', ') + ']';
        });
    });
}
var indexOf = function(s, substring) {
    var index = s.indexOf(substring);
    if (index >= 0) {
        return index;
    } else {
        throw '"' + s + '" does not contain "' + substring + '"';
    }
};
var lastIndexOf = function(s, substring) {
    var index = s.lastIndexOf(substring);
    if (index >= 0) {
        return index;
    } else {
        throw 'string "' + s + '" does not contain "' + substring + '"';
    }
};
var startsWith = function(s, pattern) {
    return s.indexOf(pattern) == 0;
};
var endsWith = function(s, pattern) {
    return s.lastIndexOf(pattern) == s.length - pattern.length;
};
var containsSubstring = function(s, substring) {
    return s.indexOf(substring) >= 0;
};
var blank = function(s) {
    return /^\s*$/.test(s);
};
var split = function(s, separator) {
    return s.length == 0 ? [] : s.split(separator);
};
var replace = function(s, regex, replace) {
    return s.replace(regex, replace);
};
var toLowerCase = function(s) {
    return s.toLowerCase();
};
var toUpperCase = function(s) {
    return s.toUpperCase();
};
var substring = function(s, from, to) {
    return s.substring(from, to);
};
var trim = function(s) {
    s = s.replace(/^\s+/, '');
    for (var i = s.length - 1; i >= 0; i--) {
        if (/\S/.test(s.charAt(i))) {
            s = s.substring(0, i + 1);
            break;
        }
    }
    return s;
};
var asNumber = Number;
var asBoolean = function(s) {
    return 'true' == s || 'any' == s;
};
var asRegexp = function(s) {
    return new RegExp(s);
};
function registerListener(eventType, obj, listener) {
    if (obj.addEventListener) {
        obj.addEventListener(eventType, listener, false);
        return function() {
            obj.removeEventListener(eventType, listener, false);
        }
    } else {
        var type = 'on' + eventType;
        obj.attachEvent(type, listener);
        return function() {
            obj.detachEvent(type, listener);
        }
    }
}
var onLoad = curry(registerListener, 'load');
var onUnload = curry(registerListener, 'unload');
var onBeforeUnload = curry(registerListener, 'beforeunload');
var onResize = curry(registerListener, 'resize');
var onKeyPress = curry(registerListener, 'keypress');
var onKeyUp = curry(registerListener, 'keyup');
window.width = function() {
    return window.innerWidth ? window.innerWidth : (document.documentElement && document.documentElement.clientWidth) ? document.documentElement.clientWidth : document.body.clientWidth;
};
window.height = function() {
    return window.innerHeight ? window.innerHeight : (document.documentElement && document.documentElement.clientHeight) ? document.documentElement.clientHeight : document.body.clientHeight;
};
        var heartbeatUpdateListeners = [];
        namespace.onHeartbeatUpdate = function(callback) {
            append(heartbeatUpdateListeners, callback);
        };
        onLoad(window, function() {
            var connection = namespace.push.connection;
            connection.onReceive(function(header, text, xml) {
                var interval = header('ice.push.heartbeat');
                if (interval) {
                    namespace.push.connection.changeHeartbeatInterval(Number(interval));
                    broadcast(heartbeatUpdateListeners, [Number(interval)]);
                }
            });
            namespace.push.pauseBlockingConnection = function(url) {
                namespace.push.connection.pauseConnection();
                namespace.push.connection.controlRequest(noop, function(header) {
                    header('ice.parkids', 'true');
                    header('ice.notifyBack', url)
                }, noop);
                namespace.push.connection.pauseConnection();
            };
            namespace.push.resumeBlockingConnection = function() {
                connection.resumeConnection();
            };
        });
    })(window.ice);
}
