require("../vendors/jquery.bootstrap-touchspin.min.js")
require("../vendors/jquery.maskedinput.min.js")
ko.bindingHandlers.restext = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, context) {
        var text = _h.getLocalizedText(ko.utils.unwrapObservable(valueAccessor()));
        if ($(element).hasClass("control-label")) {
            var size = _h.calDim(text, "11px", "Iransans", "400");
            $(element).css("width", (size[1] + 20) + "px");
        }
        ko.bindingHandlers.text.update(
            element,
            function () {
                return text;
            },
            allBindingsAccessor,
            viewModel,
            context);
    }
};
ko.bindingHandlers.resattr = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, context) {
        var json = ko.utils.unwrapObservable(valueAccessor());
        for (var attr in json) {
            var text = _h.getLocalizedText(json[attr]);
            ko.bindingHandlers.attr.update(
                element,
                function () {
                    var x = {};
                    x[attr] = text;
                    return x;
                },
                allBindingsAccessor,
                viewModel,
                context);
        }
    }
}
ko.bindingHandlers.restitle = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, context) {
        var json = ko.utils.unwrapObservable(valueAccessor());
        var text = _h.getLocalizedText(json['title'], json['entityName']);
        ko.bindingHandlers.attr.update(
            element,
            function () {
                return { title: text };
            },
            allBindingsAccessor,
            viewModel,
            context);
    }
}
ko.bindingHandlers.restext.getText = _h.getLocalizedText;
ko.bindingHandlers.label = {
    init: function () {
        return { controlsDescendantBindings: true };
    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var $element = $(element),
            value = valueAccessor(),
            color = value["color"],
            text = value["text"];
        if (value === null || value === undefined)
            throw new Error('label binding value is null');

        if (element.nodeType === (typeof Node !== 'undefined' && Node.ELEMENT_NODE || 1)) {
            $element.removeClass("label-info label-danger label-success label-default label-warning label-none");
            switch (color) {
                case "green":
                    $element.addClass('label').addClass('label label-success').text(text);
                    break;
                case "red":
                    $element.addClass('label').addClass('label label-danger').text(text);
                    break;
                case "orange":
                    $element.addClass('label').addClass('label label-warning').text(text);
                    break;
                case "blue":
                    $element.addClass('label').addClass('label label-info').text(text);
                    break;
                case "navy":
                    $element.addClass('label').addClass('label label-primary').text(text);
                    break;
                case "gray":
                    $element.addClass('label').addClass('label label-default').text(text);
                    break;
                case "none":
                    $element.addClass('label').addClass('label label-none').text(text);
                    break;
                case "":
                    $element.addClass('label').addClass('label label-none').text(text);
                    break;
            }
        }
    }
};
ko.bindingHandlers.touchSpin = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var allBindings = allBindingsAccessor(),
            value = ko.utils.unwrapObservable(valueAccessor()),
            touchSpinOptions = allBindings.touchSpinOptions || {},
            defaults = ko.bindingHandlers.touchSpin.defaults,
            $element = $(element);

        var options = $.extend(false, { initval: value }, defaults, touchSpinOptions);

        ko.bindingHandlers.value.init(element, valueAccessor, allBindingsAccessor);
        $element.TouchSpin(options);
        $element.parent(".input-group").css("width", "96%");
        ko.bindingHandlers.touchSpin.updateEnableState(element, allBindings);
    },
    update: function (element, valueAccessor, allBindingsAccessor) {
        var allBindings = allBindingsAccessor();

        ko.bindingHandlers.value.update(element, valueAccessor);
        ko.bindingHandlers.touchSpin.updateEnableState(element, allBindings);
    },
    updateEnableState: function (element, allBindings) {
        var $element = $(element),
            $plus = $element.parent().find(".bootstrap-touchspin-up"),
            $minus = $element.parent().find(".bootstrap-touchspin-down");

        if (allBindings.enable !== undefined) {
            if (ko.utils.unwrapObservable(allBindings.enable) === true) {
                $plus.removeAttr('disabled');
                $minus.removeAttr('disabled');
            } else {
                $plus.attr('disabled', 'disabled');
                $minus.attr('disabled', 'disabled');
            }
        }

        if (allBindings.disable !== undefined) {
            if (ko.utils.unwrapObservable(allBindings.disable) === false) {
                $plus.removeAttr('disabled');
                $minus.removeAttr('disabled');
            } else {
                $plus.attr('disabled', 'disabled');
                $minus.attr('disabled', 'disabled');
            }
        }
    },
    defaults: {
        min: 1,
        max: 20,
        initval: "",
        step: 1,
        verticalbuttons: true,
        decimals: 0,
        stepinterval: 20,
        forcestepdivisibility: 'round',  // none | floor | round | ceil
        stepintervaldelay: 500,
        prefix: "",
        postfix: "",
        prefix_extraclass: "",
        postfix_extraclass: "",
        booster: true,
        boostat: 10,
        maxboostedstep: false,
        mousewheel: false
    }
};
ko.bindingHandlers.tooltip = {
    'init': function (element, valueAccessor) {
        var local = ko.utils.unwrapObservable(valueAccessor());
        var options = {};

        ko.utils.extend(options, ko.bindingHandlers.tooltip.options);
        ko.utils.extend(options, local);
        $(element).tooltip(options);
        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).tooltip("destroy");
        });
    },
    'update': function (element, valueAccessor) {
        var local = ko.utils.unwrapObservable(valueAccessor());
        var options = {};
        ko.utils.extend(options, ko.bindingHandlers.tooltip.options);
        ko.utils.extend(options, local);
        $(element).data("bs.tooltip").options.title = options.title;
    },
    options: {
        placement: "top",
        trigger: "hover"
    }
};
ko.extenders.inputNumberFormatter = function (target, options) {
    target.formatted = ko.computed({
        read: function () {
            if (target() === null || target() === undefined || target() === "")
                return "";
            if (target() === "-")
                return "-";
            var temp = ko.isObservable(target) ? target() : target;
            var decimalPart,
                numberPart;
            var decimalNumber = ko.isObservable(options["decimalNumber"]) ? options["decimalNumber"]() : options["decimalNumber"];
            if (decimalNumber) {
                if (temp.toString().indexOf(".") !== -1) {
                    numberPart = temp.toString().split(".")[0];
                    decimalPart = temp.toString().split(".")[1];
                    if (options["negative"])
                        return numberPart.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + "." + decimalPart;
                    else
                        return numberPart.toString().replace('-', '').replace(/\B(?=(\d{3})+(?!\d))/g, ",") + "." + decimalPart;
                } else {
                    if (options["negative"])
                        return temp.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
                    else
                        return temp.toString().replace('-', '').replace(/\B(?=(\d{3})+(?!\d))/g, ",");
                }
            } else {
                if (options["negative"])
                    return target().toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
                else
                    return target().toString().replace('-', '').replace(/\B(?=(\d{3})+(?!\d))/g, ",");
            }
        },
        write: function (newValue) {
            var decimalPart,
                numberPart;
            var current = target();
            var hasChar = _h.stringHasAlphabet(newValue);
            if (hasChar) {
                target(undefined);
                target.notifySubscribers(undefined);
            } else {
                var newValueAsNum;
                var decimalNumber = ko.isObservable(options["decimalNumber"]) ? options["decimalNumber"]() : options["decimalNumber"];
                if (decimalNumber) {
                    newValueAsNum = String(newValue).replace(/[^0-9\.\-]/g, '');
                } else {
                    if (newValue.toString().indexOf(".") !== -1) {
                        numberPart = newValue.toString().split(".")[0];
                        decimalPart = newValue.toString().split(".")[1];
                        newValueAsNum = String(numberPart).replace(/[^0-9\-]/g, '');
                    } else {
                        newValueAsNum = String(newValue).replace(/[^0-9\-]/g, '');
                    }
                }
                var valueToWrite = newValueAsNum;
                if (valueToWrite !== current) {
                    target(valueToWrite);
                    if (options.callback)
                        options.callback(valueToWrite);
                } else {
                    if (newValue !== current) {
                        target.notifySubscribers(valueToWrite);
                        if (options.callback)
                            options.callback(valueToWrite);
                    }
                }
            }
        }
    }).extend({ notify: 'always' });
    return target;
};
ko.bindingHandlers.singleOrDoubleClick = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var singleHandler = valueAccessor().click,
            doubleHandler = valueAccessor().dblclick,
            delay = valueAccessor().delay || 300,
            clicks = 0;

        $(element).click(function (event) {
            clicks++;
            if (clicks === 1) {
                setTimeout(function () {
                    if (clicks === 1) {
                        if (singleHandler !== undefined) {
                            singleHandler.call(viewModel, bindingContext.$data, event);
                        }
                    } else {
                        if (doubleHandler !== undefined) {
                            doubleHandler.call(viewModel, bindingContext.$data, event);
                        }
                    }
                    clicks = 0;
                }, delay);
            }
        });
    }
};
ko.bindingHandlers.foreachprop = {
    transformObject: function (obj) {
        var properties = [];
        ko.utils.objectForEach(obj, function (key, value) {
            properties.push({ key: key, value: value });
        });
        return properties;
    },
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var properties = ko.pureComputed(function () {
            var obj = ko.utils.unwrapObservable(valueAccessor());
            return ko.bindingHandlers.foreachprop.transformObject(obj);
        });
        ko.applyBindingsToNode(element, { foreach: properties }, bindingContext);
        return { controlsDescendantBindings: true };
    }
}
ko.bindingHandlers.debug = {
    init: function (element, valueAccessor) {
        console.log('Knockoutbinding:');
        console.log(element);
        console.log(ko.toJS(valueAccessor()));
    }
}
ko.subscribable.fn.supsendableSubscribe = function (callback, callbackTarget, event) {
    var isSuspended = false;
    return ko.utils.extend(
        this.subscribe(function () {
            if (!isSuspended)
                return callback.apply(this, arguments);
        }, callbackTarget, event), {
        suspend: function () {
            isSuspended = true;
        },
        unsuspend: function () {
            isSuspended = false;
        }
    });
};
ko.extenders.formatSize = function (target, options) {
    var result = ko.computed({
        read: function () {
            return target();
        },
        write: function (newValue) {
            if (newValue) {
                var current = target();
                if (newValue >= options.min && newValue <= options.max) {
                    if (newValue !== current) {
                        target(newValue);
                    }
                } else {
                    if (newValue !== current) {
                        target.notifySubscribers(current);
                    }
                }
            }
        }
    }).extend({ notify: 'always' });
    target.upClick = function (fg) {

    };
    result(target());
    return result;
};
ko.bindingHandlers.masked = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var mask = allBindingsAccessor().mask;
        var placeholder = allBindingsAccessor().placeholder;
        var getCaretPosition = function (element) {
            var caretPos = 0, sel;
            if (document.selection) {
                element.focus();
                sel = document.selection.createRange();
                sel.moveStart('character', -element.value.length);
                caretPos = sel.text.length;
            } else if (element.selectionStart || element.selectionStart === '0') {
                caretPos = element.selectionStart;
            }
            return (caretPos);
        };
        var setCaretPosition = function (element, pos) {
            var range;
            if (element.setSelectionRange) {
                element.focus();
                element.setSelectionRange(pos, pos);
            } else if (element.createTextRange) {
                range = element.createTextRange();
                range.collapse(true);
                range.moveEnd('character', pos);
                range.moveStart('character', pos);
                range.select();
            }
        };
        $(element).mask(mask(), { placeholder: placeholder() });
        ko.utils.registerEventHandler(element, 'keypress', function () {
            var observable = valueAccessor(),
                position;

            if ($(element).val().length === 10) {
                position = getCaretPosition(this);
                observable($(element).val());
                setCaretPosition(this, position);
            }
        });
        ko.utils.registerEventHandler(element, 'blur', function () {
            var observable = valueAccessor();
            observable($(element).val());
        });
        ko.utils.registerEventHandler(element, 'change', function () {
            var observable = valueAccessor();
            observable($(element).val());
        });
    },
    update: function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        $(element).val(value);
    }
}