/// <reference path="../ScriptReference/jquery-1.7.1-vsdoc.js" />
/// <reference path="./Mediasite.Geometry.js" />
/*global Mediasite*/

if (!Mediasite) {
    var Mediasite = {};
}
Mediasite.Player = Mediasite.Player || {};


Mediasite.Player.ImageSizeProvider = function () {
    var self = this;
    var _knownSizes = {};
    var _defaultSize = new Mediasite.Geometry.Size(800, 600);
    var _lastSize = _defaultSize;
    var _imageRuler = new Mediasite.Player.ImageRuler();

    this.getSize = function (src, completed) {
        if (!src) {
            completed(Mediasite.Geometry.Size.Zero());
            return;
        }

        function foundSize(size) {
            debug('foundSize ' + size.toString());
            self.rememberSize(src, size);
            _lastSize = size;
            completed(size);
        }

        runSizer(fetchKnownSize, src, foundSize, function () {
            runSizer(makeHeadRequestForSize, src, foundSize, function () {
                runSizer(measureImageForSize, src, foundSize, function () {
                    runSizer(guessSize, src, foundSize, function () {
                        // This should never happen.
                        throw 'Failed to determine slide dimensions.';
                    });
                });
            });
        });

    };


    // Runs asynchronous sizer methods in a manner that allows failover chaining.
    function runSizer(sizer, src, success, failure) {
        sizer(src, function (size) {
            if (size) {
                success(size);
            } else {
                failure();
            }
        });
    }


    this.rememberSize = function (url, size) {
        if (url) {
            _knownSizes[url] = size;
        }

        return size;
    };


    function parseHeaderToSize(value) {
        if (typeof value !== 'string') {
            return null;
        }

        var parts = value.split('x');
        if (parts.length !== 2) {
            return null;
        }

        var x = parseInt(parts[0]);
        var y = parseInt(parts[1]);

        if (isNaN(x) || isNaN(y)) {
            return null;
        }

        return new Mediasite.Geometry.Size(x, y);
    }

    function debug(msg) {
        //console.log('[ImageSizeProvider] ' + msg);
    }


    // Sizer Methods

    function fetchKnownSize(src, callback) {
        debug('fetchKnownSize');
        callback(_knownSizes[src]);
    }

    function makeHeadRequestForSize(src, callback) {
        debug('makeHeadRequestForSize');

        if (!Mediasite.Player.ImageSizeProvider.useXHR) {
            callback(null);
            return;
        }

        var jqxhr = $.ajax(src, { type: 'HEAD', global: false })
            .done(function () {
                var headerString = jqxhr.getResponseHeader('x-native-dimensions');
                var size = parseHeaderToSize(headerString);
                callback(size);
            })
            .fail(function () {
                debug('ajax fail');
                callback(null);
            });
    }

    function measureImageForSize(src, callback) {
        debug('measureImageForSize');
        _imageRuler.measure(src, function (size) {
            if (size && !Mediasite.Geometry.Size.Zero().equals(size)) {
                callback(size);
            } else {
                callback(null);
            }
        });
    }

    function guessSize(src, callback) {
        debug('guessSize');

        // Consider adding more sophisticated guessing logic.
        callback(_lastSize || _defaultSize);
    }
};
Mediasite.Player.ImageSizeProvider.useXHR = (window.location.href.indexOf('file:') != 0);


Mediasite.Player.ImageRuler = function () {
    var img = $('<img />');

    this.measure = function (src, callback) {
        img.bind({
            'load': function () {
                clearImg();
                callback(new Mediasite.Geometry.Size(this.width, this.height));
            },
            'error': function () {
                clearImg();
                callback(Mediasite.Geometry.Size.Zero());
            }
        });

        if (typeof src === 'string' && src.length > 0) {
            img.attr('src', src);
        } else {
            img.trigger('error');
        }
    };

    function clearImg() {
        img.unbind();
        img.src = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';
    }
}