define([
      'knockout', 'text!./efis.svg', 'sprintf'
], function(ko, htmlString, sprintf) {

    function ViewModel(params) {
        var self = this;
        params = params||{}
        
        self.rateLimit = params.rateLimit || 100;

        self.propertyMap = {
            pitch : 'pitch',
            roll : 'roll',
            airspeed : 'airspeed',
            altitude : 'altitude',
            heading : 'heading',
            slip : 'slip'
        }

        this.pitch = ko.observable(0).extend({
            fgprop : self.propertyMap.pitch
        }).extend({rateLimit: self.rateLimit });
        this.roll = ko.observable(0).extend({
            fgprop : self.propertyMap.roll
        }).extend({rateLimit: self.rateLimit });
        this.airspeed = ko.observable(0).extend({
            fgprop : self.propertyMap.airspeed
        }).extend({rateLimit: self.rateLimit });
        this.altitude = ko.observable(0).extend({
            fgprop : self.propertyMap.altitude
        }).extend({rateLimit: self.rateLimit });
        this.heading = ko.observable(0).extend({
            fgprop : self.propertyMap.heading
        }).extend({rateLimit: self.rateLimit });
        
        this.slip = ko.observable(0).extend({
            fgprop : self.propertyMap.slip
        }).extend({rateLimit: self.rateLimit });

        this.horizonAnimation = ko.pureComputed(function() {
            return "rotate(" + (-self.roll()) + " 512 384) translate(0 " + (self.pitch() * 20) + ")";
        });

        this.compassAnimation = ko.pureComputed(function() {
            return "rotate(" + (-self.heading()) + " 512 1108.175)";
        });

        this.headingTextAnimation = ko.pureComputed(function() {
            return sprintf.sprintf("%03d", Math.round(self.heading()));
        });

        this.asiTextAnimation = ko.pureComputed(function() {
            return sprintf.sprintf("%3d", Math.round(self.airspeed()));
        });

        this.altimeterThousandsTextAnimation = ko.pureComputed(function() {
            return sprintf.sprintf("%2d", self.altitude() / 1000);
        });

        this.altimeterHundretsTextAnimation = ko.pureComputed(function() {
            return sprintf.sprintf("%03d", Math.abs(self.altitude() % 1000));
        });

        this.asiLadderLabelAnimation0 = ko.pureComputed(function() {
            return self._getAsiLadderLabel(0);
        });

        this.asiLadderLabelAnimation1 = ko.pureComputed(function() {
            return self._getAsiLadderLabel(1);
        });

        this.asiLadderLabelAnimation2 = ko.pureComputed(function() {
            return self._getAsiLadderLabel(2);
        });

        this.asiLadderLabelAnimation3 = ko.pureComputed(function() {
            return self._getAsiLadderLabel(3);
        });

        this.asiLadderLabelAnimation4 = ko.pureComputed(function() {
            return self._getAsiLadderLabel(4);
        });

        this.altitudeLadderLabelAnimation0 = ko.pureComputed(function() {
            return self._getAltitudeLadderLabel(0);
        });

        this.altitudeLadderLabelAnimation1 = ko.pureComputed(function() {
            return self._getAltitudeLadderLabel(1);
        });

        this.altitudeLadderLabelAnimation2 = ko.pureComputed(function() {
            return self._getAltitudeLadderLabel(2);
        });

        this.altitudeLadderLabelAnimation3 = ko.pureComputed(function() {
            return self._getAltitudeLadderLabel(3);
        });

        this.altitudeLadderLabelAnimation4 = ko.pureComputed(function() {
            return self._getAltitudeLadderLabel(4);
        });

        this.asiLadderLabelTransform = ko.pureComputed(function() {
            var v = self.airspeed();
            var y = v > 40 ? 38 * 8 + 152 * (v % 20) / 20 : 38 * v / 5;
            return "translate(0 " + y + ")";
        });

        this.asiLadderTransform = ko.pureComputed(function() {
            var v = self.airspeed();
            var y = v > 40 ? 38 * 8 + 76 * (v % 10) / 10 : 38 * v / 5;
            return "translate(0 " + y + ")";
        });

        this.altimeterLadderLabelTransform = ko.pureComputed(function() {
            var v = self.altitude();
            var y = 152 * (v % 200) / 200;
            return "translate(0 " + y + ")";
        });

        this.altimeterLadderTransform = ko.pureComputed(function() {
            var v = self.altitude();
            var y = 76 * (v % 100) / 100;
            return "translate(0 " + y + ")";
        });

        this.slipSkidTransform = ko.pureComputed(function() {
            var v = self.slip() * -71.6125;
            var x = v < -125 ? -125 : v > 125 ? 125 : v;
            return "translate(" + x + " 0)";
        });
    }

    ViewModel.prototype._getAsiLadderLabel = function(n) {
        // draw labels every 20kt
        var v = ((this.airspeed() / 20) | 0) * 20 - 40;
        v = v < 0 ? 0 : v;
        return sprintf.sprintf("%3d", v + n * 20)
    }

    ViewModel.prototype._getAltitudeLadderLabel = function(n) {
        // draw labels every 200ft
        var v = ((this.altitude() / 200) | 0) * 2 - 4;
        return sprintf.sprintf("%2.1f", (v + n * 2) / 10);
    }

    // Return component definition
    return {
        viewModel : ViewModel,
        template : htmlString
    };
});