/*

This handles the e-signatures.  It is loaded automatically from the ascx 
file, so there is no need to worry about including this elsewhere.  All 
of the dependencies (except jQuery) are loaded automatically as well.

See the Signature.ascx code-behind for details on how to use this widget.

*/


/*
Signature validation function
*/
function valSignature(jSig, jContext) {
    var result = jSig.find('.prompt img').height() > 0;
    setTimeout(function () {
        $(window).trigger('signature_validated', [jSig, result]);
    }, 0);
    return result;
}


/*
Encapsulates a signature control
*/
var Signature = function (jSig, jContext, defaultSigUrl) {
    var that = this;
    this.container = jSig;
    this.context = jContext;
    this.defaultSigUrl = defaultSigUrl;
    this.dialog = this.container.find('.dialog');
    this.emptySVG = 'image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4xIiB3aWR0aD0iMCIgaGVpZ2h0PSIwIiB2aWV3Qm94PSIwIDAgMCAwIiBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ0cnVlIj48L3N2Zz4=';
    this.image = this.container.find('img');
    this.timestamp = this.container.find('.timestamp');
    this.pad = this.container.find('.pad');
    this.fakePad = this.container.find('.fakePad');
    this.fakePadData = this.emptySVG;
    this.prompt = this.container.find('.prompt');

    // hidden fields
    var inputs = this.container.find('input');
    this.chkChanged = $(inputs[0]);
    this.txtContext = $(inputs[1]);
    this.txtData = $(inputs[2]);
    
    // Clear the signature pad and saved sig
    this.clear = function () {
        if (this.isVisible()) {
            this.pad.jSignature('clear');
            this.fakePad.html('');
            this.fakePad.removeClass('show');
            this.fakePadData = this.emptySVG;
        }
    };

    // Copy the signature from the previous signature
    this.copy = function () {
        that.fakePadData = this.emptySVG;
        this.pad.jSignature('clear');

        var payload = { action: "get" };
        $.ajax(this.defaultSigUrl, { method: "POST", data: payload, dataType: 'text' })
        .done(function (data) {
            that.fakePadData = data;
            that.fakePad.html('<img src="data:' + data + '">');
            that.fakePad.addClass('show');
        });
    };

    // Get the sig from the pad so we can save on postback
    this.save = function () {
        if (!this.isVisible()) {
            var data = this.emptySVG;
            this.timestamp.addClass('hidden');
        }
        else if (this.fakePad.hasClass('show')) {
            var data = this.fakePadData;
        }
        else {

            var svg = this.pad.jSignature('getData', 'svg')[1];

            // The easy way is to call join on getData's return value...
            // Unfortunately, IE messes up if the SVG and CSS aren't *just* right.
            // We modify the SVG before setting the data so that IE works.
            var data = svg.replace(/(\<svg xmlns.*?version="1.1") width="(\d+)" height="(\d+)"/, '$& viewBox="0 0 $2 $3" preserveAspectRatio="true"');
            data = 'image/svg+xml;base64,' + btoa(data);

            // We need width/height
            var width = 0, height = 0;
            var sizesExtracted = svg.match(/(\<svg xmlns.*?version="1.1") width="(\d+)" height="(\d+)"/);
            if (sizesExtracted.length == 4) {
                width = sizesExtracted[2];
                height = sizesExtracted[3];
            }

            // Set up our timestamp.  We'll use the server's local time.
            this.timestamp.addClass('hidden');
            if (width > 0 && height > 0) {
                var now = this.getServerLocalTime();
                var fmtDate = '' + (now.getMonth() + 1) + '/' + now.getDate() + '/' + now.getFullYear();
                var fmtTime = '' + (now.getHours() % 12 || '12') + ':' + ("00" + now.getMinutes()).substr(-2, 2) + ":" + ("00" + now.getSeconds()).substr(-2, 2) + " " + ((now.getHours() < 12) ? "am" : "pm");
                this.timestamp.text("Digitally signed on " + fmtDate + " at " + fmtTime + ".");
                this.timestamp.removeClass('hidden');
            }
        }
        this.image.attr('src', 'data:' + data);
        this.chkChanged.prop('checked', true);
        this.txtContext.val(getFormDump(this.context));
        this.txtData.val(data);

        if (this.defaultSigUrl) {
            var payload = { action: "update", data: data };
            $.ajax(this.defaultSigUrl, { method: "POST", data: payload });
        }
    };

    // Show/hide the pad
    this.show = function () {
        this.dialog.addClass('visible');
        this.pad.jSignature();
    };
    this.hide = function () {
        this.pad.html('');
        this.dialog.removeClass('visible');
    };
    this.isVisible = function () {
        return this.dialog.hasClass('visible');
    };


    /* Internals */

    // Get the local time at the server
    this.getServerLocalTime = function () {
        var test = "6/1/2018 12:00";
        var serverOffset = new Date(test).getTime() - (new Date(test + ' CDT')).getTime();
        var local = new Date().getTime();
        var server = local + serverOffset;
        return new Date(server);
    }

    // initialize our library here
    this.init = function () {

        // Set our prompt text
        this.prompt.find('h3').text('Click to Sign');

        // On context changed, we need to clear our sig
        this.context.find(':input').change(function (e) {
            if ($(this).hasClass('ignore-on-sig-validation'))
                return;
            that.clear();
        });

        // Buttons
        this.dialog.find('.cancel').click(function (e) {
            that.hide();
            return false;
        });
        this.dialog.find('.clear').click(function (e) {
            that.clear();
            return false;
        });
        this.dialog.find('.copy').click(function (e) {
            that.copy();
            return false;
        });
        this.dialog.find('.default').click(function (e) {
            that.save();
            that.hide();
            return false;
        });

        // On prompt clicked, show signature pad
        this.prompt.click(function () {
            that.show()
        });

    }

    // This handles loading dependencies.
    // If/when all is okay, our init() is called.
    Signature.initialize(this);

};

// Loading status
Signature.loading = false;
Signature.loaded = false;
Signature.initQueue = [];

// Initialize our class
Signature.initialize = function (sig) {
    if (Signature.loaded) {
        sig.init();
    } else if (Signature.loading) {
        Signature.initQueue.push(sig);
    } else {
        Signature.initQueue.push(sig);
        Signature.loadDependencies(function () {
            Signature.loaded = true;
            var queue = Signature.initQueue;
            for (var i = 0; i != queue.length; ++i)
                $.proxy(queue[i].init(), queue[i]);
        });
    }
};

// Load up any dependencies
Signature.loadDependencies = function (success) {
    Signature.loading = true;

    var loadResource = function (uri, success) {
        $.ajax(uri, { cache: true, dataType: "script" })
        .done(success)
        .fail(function () {
            Signature.loadDependencies = function () { };
            $('.signature h3').text('Error');
            alert('Error loading signature pad code.');
        });
    };

    var loadCompat = function () {
        return $.ajax("/_assets/scripts/flashcanvas.js", { cache: true, dataType: "script" });
    };
    var loadSignature = function () {
        return $.ajax("/_assets/scripts/jSignature.min.js", { cache: true, dataType: "script" });
    };

    // We need jSignature.  If IE < 9, we also needs flashcanvas.
    if (typeof window.needsCompatScripts != 'undefined') {
        loadResource("/_assets/scripts/flashcanvas.js", function () {
            loadResource("/_assets/scripts/jSignature.min.js", success);
        });
    } else {
        loadResource("/_assets/scripts/jSignature.min.js", success);
    }

};
