﻿//Enumerations
var ToolType = { "None": 0, "Lamp": 1, "ArchitecturalModel": 2, "Vase": 3, "Bookend": 4 };
var MeasureUnit = { 'MM': 'MM', 'Inch': 'Inch' };
var ModelPreviewType = { "Projections": 0, "Stripe": 1 };
var State = {
    'WaitingForUpload': 1,
    'Uploading': 2,
    'GeneratingPreview': 3,
    'Fixing': 4,
    'CalculatingPrice': 5,
    'Succeed': 6,
    'CantProcessFile': 7,
    'CantBeFixed': 8,
    'CantCalculatePrice': 9
};

function ScaleRatio(value) {
    var _Value = value;
    var _MaxLimit = 1e6;
    var _MinLimit = 1e-6;

    this.Value = function() {
        return _Value;
    }

    this.Numerator = function() {
        if (_Value >= 1) {
            return _Value;
        }
        else {
            return 1;
        }
    }

    this.Denominator = function() {
        if (_Value >= 1) {
            return 1;
        }
        else {
            return 1 / _Value;
        }
    }

    this.Percent = function() {
        return _Value * 100;
    }

    this.ApplyLimit = function() {
        if (_Value > _MaxLimit) {
            _Value = _MaxLimit;
        }
        if (_Value < _MinLimit) {
            _Value = _MinLimit;
        }
        return new ScaleRatio(_Value);
    }
}

ScaleRatio.Default = function() {
    return new ScaleRatio(parseFloat(1));
}

ScaleRatio.FromNumerator = function(numeratorValue) {
    return new ScaleRatio(parseFloat(numeratorValue));
}

ScaleRatio.FromDenominator = function(denominatorValue) {
    return new ScaleRatio(1 / denominatorValue);
}

ScaleRatio.FromPercent = function(percentValue) {
    return new ScaleRatio(percentValue / 100);
}

function ModelProcessingResult(result) {
    var _State = result.clientState;
    var _PreviewImage = result.previewImage;
    var _DimX = result.modelParameters == null ? 0 : result.modelParameters.DimX;
    var _DimY = result.modelParameters == null ? 0 : result.modelParameters.DimY;
    var _DimZ = result.modelParameters == null ? 0 : result.modelParameters.DimZ;
    var _Price = result.price;
    var _CurrencySymbol = result.currencySymbol;
    var _ModelPreviewDescriptor = result.previewDescriptor;

    this.GetState = GetState;
    this.GetPreviewImage = GetPreviewImage;
    this.GetDimX = GetDimX;
    this.GetDimY = GetDimY;
    this.GetDimZ = GetDimZ;
    this.GetPrice = GetPrice;
    this.GetCurrencySymbol = GetCurrencySymbol;
    this.GetModelPreviewDescriptor = GetModelPreviewDescriptor;

    function GetState() {
        return _State;
    }

    function GetPreviewImage() {
        return _PreviewImage;
    }

    function GetModelPreviewDescriptor() {
        return _ModelPreviewDescriptor;
    }

    function GetDimX() {
        return _DimX;
    }

    function GetDimY() {
        return _DimY;
    }

    function GetDimZ() {
        return _DimZ;
    }

    function GetPrice() {
        return _Price;
    }

    function GetCurrencySymbol() {
        return _CurrencySymbol;
    }
}

function InteractivePreviewStrategy(placeholderElement, previewDescriptor)
{
    var _previewDescriptor;
    var _placeholderElement;

    this.PreviewAreaHolder = function(placeholderElement) {
        if (typeof placeholderElement == "undefined") {
            return _placeholderElement;
        }
        _placeholderElement = placeholderElement;
    }

    this.PreviewDescriptor = function(previewDescriptor) {
        if (typeof previewDescriptor == "undefined") {
            return _previewDescriptor;
        }
        _previewDescriptor = previewDescriptor;
    }

    this.PreviewAreaHolder(placeholderElement);
    this.PreviewDescriptor(previewDescriptor);
}


function StripePreviewStrategy(placeholderElement, previewDescriptor) {

    InteractivePreviewStrategy.call(this, placeholderElement, previewDescriptor);
    
    this.GetFrameWidth = function()
    {
        return this.PreviewDescriptor().FrameWidth;
    }
    
    this.GetFramesNumber = function()
    {
        return this.PreviewDescriptor().FramesNumber;
    }
    
    this.GetStripeFileUrl = function()
    {
        return this.PreviewDescriptor().StripeFileUrl;
    }
}

StripePreviewStrategy.prototype.Init = function () {
    var _useInertiaEffect = false;
    var _this = this;
    var _doDrag = false;
    var _mouseStartXPos = 0;
    var _currentStripeFrameIdx = 0;
    var _initialFrameIdx = 0

    var _rotationStartTime;
    var _rotationEndTime;

    var _velocity = 0;
    var _delayTime = 0;
    var _framesPassed = 0;
    var _mouseIconElmnt = $("#rotateMouseIcoID").get();
    InitPlaceholder(this.PreviewAreaHolder(), this.GetStripeFileUrl());

    SetStripeFrameByIdx(this.PreviewAreaHolder(), _currentStripeFrameIdx);

    function StartRotation(mouseXPos, useInertiaEffect) {
        _useInertiaEffect = useInertiaEffect;
        _mouseStartXPos = mouseXPos;
        _velocity = 0;
        _framesPassed = 0;
        _doDrag = true;
        _rotationStartTime = new Date();
        ShowRotationBtn(false);
    }

    function StopRotation(mouseXPos) {
        if (!_doDrag) {
            return;
        }

        _doDrag = false;

        ShowRotationBtn(true);

        if (!_useInertiaEffect) {
            return;
        }
        _rotationEndTime = new Date();
        var rotationTime = new Date(_rotationEndTime - _rotationStartTime).getSeconds();
        rotationTime = rotationTime == 0 ? 1 : rotationTime;

        _velocity = (_framesPassed) / rotationTime;
        _initialFrameIdx = _currentStripeFrameIdx;

        
        recalculateVelocity(1);
        if (Math.abs(_velocity) > 1) {
            $(_this.PreviewAreaHolder()).clearQueue();
            $(_this.PreviewAreaHolder()).queue(autoRotator).delay(_delayTime).dequeue();
        }
    }

    function autoRotator() {
        var acceleration = 0.95;
        if (Math.abs(_velocity) > 1) {
            var rotateTo = _velocity > 0 ? 1 : -1;
            SetStripeFrameByIdx(_this.PreviewAreaHolder(), _currentStripeFrameIdx + rotateTo);
            recalculateVelocity(acceleration);
            $(_this.PreviewAreaHolder()).queue(autoRotator).delay(_delayTime).dequeue();
        }
    }

    function recalculateVelocity(acceleration) {
        _velocity *= acceleration;
        _delayTime = Math.floor(1 / Math.abs(_velocity) * 1000);
        if (_delayTime < 75) {
            _delayTime = 75;
        }
    }
    function ShowRotationBtn(doShow) {
        var element = $(_mouseIconElmnt);
        if (doShow) {
            if ($.browser.msie) {
                element.show();
            } else {
                element.fadeIn(50);
            }
        } else {
            if ($.browser.msie) {
                element.hide();
            } else {
                element.fadeOut(50);
            }
        }
    }
    function InitPlaceholder(placeholder, stripeUrl) {
        $(placeholder).css('position', 'relative');
        $(placeholder).css('background-image', "url('" + stripeUrl + "')");
        $(placeholder).css('background-repeat', "no-repeat");
        $(placeholder).unbind('mousemove');
        $(placeholder).unbind('mousedown');
        $(placeholder).unbind('dragstart', DocumentOnDragStartHandler);
        $(document).unbind('mouseup');

        $(placeholder).mousedown(function (e) {
            StartRotation(GetMouseXPosition(e), e.ctrlKey);
            return false;
        });

        $(document).mouseup(function (e) {
            StopRotation(GetMouseXPosition(e));
            return false;
        });

        $(placeholder).mousemove(function (e) {
            if (!_doDrag)
                return;
            var mouseXPos = GetMouseXPosition(e);
            var frameOffset = GetFramesOffset(mouseXPos);
            if (frameOffset != 0) {
                SetStripeFrameByIdx(placeholder, _initialFrameIdx + frameOffset);
                _framesPassed = frameOffset;
            }
        });

        $(placeholder).bind('dragstart', DocumentOnDragStartHandler);
        $(_mouseIconElmnt).show();
    }

    function DocumentOnDragStartHandler(e) {
        return false;
    }

    function GetFramesOffset(currentMouseXPos) {
        var ratio = 0.75;
        var frameWidth = _this.GetFrameWidth();
        var framesNumber = _this.GetFramesNumber();
        var sectorWidth = frameWidth / framesNumber * ratio;
        var result = Math.floor((currentMouseXPos - _mouseStartXPos) / sectorWidth);
        return result
    }

    function SetStripeFrameByIdx(placeholder, frameIdx) {
        _currentStripeFrameIdx = NormalizeStripeFrameIdx(frameIdx);
        var frameStartXPosition = _currentStripeFrameIdx * _this.GetFrameWidth();

        $(placeholder).css('background-position', -frameStartXPosition + 'px 0px');
    }

    function NormalizeStripeFrameIdx(frameIdx) {
        var frameIdxToSet = frameIdx % _this.GetFramesNumber();
        if (frameIdx < 0) {
            frameIdxToSet = _this.GetFramesNumber() + frameIdxToSet;
        }
        return frameIdxToSet;
    }

    function GetMouseXPosition(eventObj) {
        return eventObj.pageX - $(eventObj.target).offset().left;
    }
}


function ProjectionsPreviewStrategy(placeholderElement, previewDescriptor) {
    InteractivePreviewStrategy.call(this, placeholderElement, previewDescriptor);

    this.IsoFileUrl = function() {
        return this.PreviewDescriptor().IsoFileUrl;
    }
    this.FrontFileUrl = function() {
        return this.PreviewDescriptor().FrontFileUrl;
    }
    this.BackFileUrl = function() {
        return this.PreviewDescriptor().BackFileUrl;
    }
    this.LeftFileUrl = function() {
        return this.PreviewDescriptor().LeftFileUrl;
    }
    this.RightFileUrl = function() {
        return this.PreviewDescriptor().RightFileUrl;
    }
    this.TopFileUrl = function() {
        return this.PreviewDescriptor().TopFileUrl;
    }
    this.BottomFileUrl = function() {
        return this.PreviewDescriptor().BottomFileUrl;
    }
}


ProjectionsPreviewStrategy.prototype.Init = function() {
    var _this = this;
    var hookOverImgUrl = "/images/main/preview_button_rollover.png";
    var hookOutImgUrl = "/images/main/preview_button.png";

    var tempImg = new Image();

    tempImg.src = hookOverImgUrl;
    tempImg.src = hookOutImgUrl;
    tempImg.src = _this.IsoFileUrl();
    tempImg.src = _this.FrontFileUrl();
    tempImg.src = _this.BackFileUrl();
    tempImg.src = _this.LeftFileUrl();
    tempImg.src = _this.RightFileUrl();
    tempImg.src = _this.TopFileUrl();
    tempImg.src = _this.BottomFileUrl();
    
    
    $(".prevs-cntrls img").unbind('hover');
    $(".prevs-cntrls img").unbind('mouseout');
    //show bullets
    $(".prevs-cntrls").css('display', 'block');

    $(".prevs-cntrls img").hover(function() {
        $(this).attr({ "src": hookOverImgUrl });
    });
    $(".prevs-cntrls img").mouseout(function() {
        $(this).attr({ "src": hookOutImgUrl });
    });


    $("#frnt").hover(function() {
        ShowProjection(_this.FrontFileUrl());
    });
    $("#bck").hover(function() {
        ShowProjection(_this.BackFileUrl());
    });
    $("#rght").hover(function() {
        ShowProjection(_this.RightFileUrl());
    });
    $("#lft").hover(function() {
        ShowProjection(_this.LeftFileUrl());
    });
    $("#top").hover(function() {
        ShowProjection(_this.TopFileUrl());
    });
    $("#bttm").hover(function() {
        ShowProjection(_this.BottomFileUrl());
    });
    $("#iso").hover(function() {
        ShowProjection(_this.IsoFileUrl());
    });

    ShowProjection(_this.IsoFileUrl());

    function ShowProjection(projectionUrl) {
        $(_this.PreviewAreaHolder()).attr({ "src": projectionUrl })
    }

}

function Model() {
    var _MMToInchesRatio = 0.0393700787;

    var _ModelGuid = null;
    var _State = State.WaitingForUpload;
    var _PreviousState = State.WaitingForUpload;
    var _DimX = 0;
    var _DimY = 0;
    var _DimZ = 0;
    var _ScaleRatio = ScaleRatio.Default;
    var _Subtotal = 0;
    var _ConvertToInches = false;
    var _Status;
    var _ToolType = ToolType.None;
    var _FileUploadStartTime = null;

    this.GetModelGuid = GetModelGuid;
    this.SetModelGuid = SetModelGuid;
    this.GetState = GetState;
    this.SetState = SetState;
    this.IsStateChanged = IsStateChanged;
    this.GetDimX = GetDimX;
    this.GetDimY = GetDimY;
    this.GetDimZ = GetDimZ;
    this.HasDimensions = HasDimensions;
    this.SetDimensions = SetDimensions;
    this.SetScaleRatio = SetScaleRatio;
    this.GetScaleRatio = GetScaleRatio;
    this.SetSubtotal = SetSubtotal;
    this.GetSubtotal = GetSubtotal;
    this.SetToolType = SetToolType;
    this.GetToolType = GetToolType;
    this.SetConvertToInches = SetConvertToInches;
    this.IsPriceValid = IsPriceValid;
    this.Init = Init;
    this.ToInches = ToInches;
    this.RoundDim = RoundDim;
    this.RememberFileUploadStartTime = RememberFileUploadStartTime;
    this.CalculateFileUploadTime = CalculateFileUploadTime;

    function GetModelGuid() {
        return _ModelGuid;
    }

    function SetModelGuid(modelGuid) {
        _ModelGuid = modelGuid;
    }

    function GetState() {
        return _State;
    }

    function SetState(state) {
        _PreviousState = _State;
        _State = state;
    }

    function IsStateChanged() {
        return _State != _PreviousState;
    }

    function GetDimX() {
        return RoundDim(Convert(Scale(_DimX)));
    }

    function GetDimY() {
        return RoundDim(Convert(Scale(_DimY)));
    }

    function GetDimZ() {
        return RoundDim(Convert(Scale(_DimZ)));
    }

    function HasDimensions() {
        return (_DimX != 0 && _DimY != 0 && _DimZ != 0);
    }

    function SetDimensions(dimX, dimY, dimZ) {
        _DimX = dimX;
        _DimY = dimY;
        _DimZ = dimZ;
    }

    function GetScaleRatio() {
        return _ScaleRatio;
    }

    function SetScaleRatio(scaleRatio) {
        _ScaleRatio = scaleRatio;
    }

    function GetSubtotal() {
        return _Subtotal;
    }

    function SetSubtotal(subtotal) {
        _Subtotal = subtotal;
    }

    function IsPriceValid() {
        if (_Subtotal == null)
            return false;
        else if (_Subtotal > 0)
            return true;
        return false;
    }

    function SetConvertToInches(value) {
        _ConvertToInches = value;
    }

    function GetToolType() {
        return _ToolType;
    }

    function SetToolType(toolType) {
        _ToolType = toolType;
    }

    function Init(modelGuid, state, subtotal, dimX, dimY, dimZ, scaleRatio, convertToInches) {
        _ModelGuid = modelGuid;
        _State = state;
        _Subtotal = subtotal;
        SetDimensions(dimX, dimY, dimZ);
        _ScaleRatio = scaleRatio;
        _ConvertToInches = convertToInches;
        _Status = "Unknown";
    }

    function ToInches(mmValue) {
        return mmValue * _MMToInchesRatio;
    }

    function Scale(dimValue) {
        return dimValue * _ScaleRatio.Value();
    }

    function Convert(value) {
        if (_ConvertToInches) {
            return ToInches(value);
        }
        else {
            return value;
        }
    }

    function RoundDim(dimValue) {
        if (_ConvertToInches) {
            return dimValue.toFixed(1);
        }
        else {
            return dimValue.toFixed(0);
        }
    }

    function RememberFileUploadStartTime() {
        _FileUploadStartTime = new Date();
    }

    function CalculateFileUploadTime() {
        if (_FileUploadStartTime == null) {
            return 0;
        }

        var fileUploadEndTime = new Date();
        return (fileUploadEndTime - _FileUploadStartTime);
    }
}

function View() {
    _Calculating = "Calculating...";


    var getModelPreviewStrategy = function(previewDescriptor) {
        if (previewDescriptor == null)
            return null;

        var type = previewDescriptor.PreviewType
        if (type == ModelPreviewType.Stripe)
            return new StripePreviewStrategy($("#modelPreview")[0], previewDescriptor)
        else if (type == ModelPreviewType.Projections)
            return new ProjectionsPreviewStrategy($("#modelPreview")[0], previewDescriptor)
        else
            return null;
    }
    
    
    
    
    this.LocalizeMeasureUnit = function(measureUnit) {
        if (measureUnit == MeasureUnit.MM)
            return 'mm';
        return 'in';
    }

    this.QuantityLabel = function(quantityLabel) {
        if (typeof quantityLabel != "undefined")
            $("#lblQuantity").html(quantityLabel);
        return $("#lblQuantity").html();
    }

    this.Quantity = function(quantity) {
        if (typeof quantity != "undefined")
            $("#txtQuantity").val(quantity);
        return parseInt($("#txtQuantity").val());
    }

    this.PriceLabel = function(priceLabel) {
        if (typeof priceLabel != "undefined")
            $("#lblPrice").html(priceLabel);
        return $("#lblPrice").html();
    }

    this.Price = function(price) {
        if (typeof price != "undefined") {
            $("#lblPriceValue").text(price.toFixed(2));
            $("#lblEuroSign").show();
            if (price > 0) {
                this.AllowCheckout(true);
            }
        }

        if ($("#lblPriceValue").text() == _Calculating)
            return 0;

        return parseFloat($("#lblPriceValue").text());
    }

    this.CurrencySymbol = function(symbol) {
        if (typeof symbol != "undefined") {
            $("#lblEuroSign").text(symbol);
        }
        return $("#lblEuroSign").text();
    }

    this.SetPriceStatusCalculate = function() {
        this.AllowCheckout(false);
        $("#lblPriceValue").text(_Calculating);
        $("#lblEuroSign").hide();
    }

    this.HidePriceStatusCalculate = function() {
        $("#lblPriceValue").text("0");
        $("#lblEuroSign").show();
    }

    this.IsCalculating = function() {
        return $("#lblPriceValue").text() == _Calculating;
    }

    this.MeasureUnit = function(measureUnit) {
        if (typeof measureUnit != "undefined") {
            if (measureUnit == MeasureUnit.MM) {
                $("#rbtMM").attr('checked', 'checked');
            }
            else {
                $("#rbtInch").attr('checked', 'checked');
            }
            $("#lblUnit").text(this.LocalizeMeasureUnit(measureUnit));
        }

        if ($("#rbtMM").attr('checked') == 'checked') {
            return MeasureUnit.MM;
        }
        else {
            return MeasureUnit.Inch;
        }
    }

    this.SelectedMaterial = function() {
        return $("#cbxMaterials").val();
    }

    this.SelectedFinishing = function(finishingID) {
        if (typeof finishingID != "undefined")
            $("#cbxFinishings").val(finishingID);
        return $("#cbxFinishings").val();
    }

    this.SelectedColour = function() {
        return $("#cbxColours").val();
    }

    this.DimX = function(dimX) {
        if (typeof dimX != "undefined")
            $("#lblDimX").text(dimX);
        return parseFloat($("#lblDimX").text());
    }

    this.DimY = function(dimY) {
        if (typeof dimY != "undefined")
            $("#lblDimY").text(dimY);
        return parseFloat($("#lblDimY").text());
    }

    this.DimZ = function(dimZ) {
        if (typeof dimZ != "undefined")
            $("#lblDimZ").text(dimZ);
        return parseFloat($("#lblDimZ").text());
    }

    this.Dimensions = function(dimX, dimY, dimZ) {
        if (typeof dimX != "undefined" && typeof dimY != "undefined" && typeof dimZ != "undefined") {
            this.DimX(dimX);
            this.DimY(dimY);
            this.DimZ(dimZ);
        }
    }

    this.ScaleRatioNumerator = function(scaleRatioNumerator) {
        if (typeof scaleRatioNumerator != "undefined") {
            $("#txtScaleRatioNumerator").val(scaleRatioNumerator.toFixed(2));
        }
        return parseFloat($("#txtScaleRatioNumerator").val());
    }

    this.ScaleRatioDenominator = function(scaleRatioDenominator) {
        if (typeof scaleRatioDenominator != "undefined") {
            $("#txtScaleRatioDenominator").val(scaleRatioDenominator.toFixed(2));
        }
        return parseFloat($("#txtScaleRatioDenominator").val());
    }

    this.ScaleRatioPercent = function(scaleRatioPercent) {
        if (typeof scaleRatioPercent != "undefined") {
            $("#txtScaleRatioPercent").val(scaleRatioPercent.toFixed(2));
        }
        return parseFloat($("#txtScaleRatioPercent").val());
    }

    this.ScaleRatioSlider = function(scaleRatioPercent) {
        if (typeof scaleRatioPercent != "undefined") {            
            $("#jSlider").slider('value', scaleRatioPercent.toFixed(0));
        }
    }

    this.ScaleRatio = function(scaleRatio) {
        if (typeof scaleRatio != "undefined") {
            this.ScaleRatioSlider(scaleRatio.Percent());
            this.ScaleRatioPercent(scaleRatio.Percent());
            this.ScaleRatioNumerator(scaleRatio.Numerator());
            this.ScaleRatioDenominator(scaleRatio.Denominator());
        }
        return ScaleRatio.FromPercent(this.ScaleRatioPercent());
    }

    this.Finishings = function(finishings) {
        if (typeof finishings != "undefined") {
            $("#cbxFinishings").removeOption(/./);
            $("#cbxFinishings").addOption(finishings, false);
        }
    }

    this.Colours = function(colours) {
        if (typeof colours != "undefined") {
            $("#cbxColours").removeOption(/./);
            $("#cbxColours").addOption(colours, false);
        }
    }

    this.SetPreview = function(previewDescriptor) {
        var previewStrategy = getModelPreviewStrategy(previewDescriptor)
        if (previewStrategy != null) {
            previewStrategy.Init();
        }
    }
    this.InitSlideShow = function() {
        $(".slide-img").cycle({ speed: 1300, timeout: 5800 });
    }
    this.StopSlideShow = function() {
        $(".slide-img").css({ "display": "none" })
    }
    this.AllowCheckout = function(allow) {
        $("#frmOrder").attr("action", "/Home/MakeOrder");
        if (allow) {
            $("#btnMakeOrder").attr("class", "button CheckOutButton")
            $("#btnMakeOrder").removeAttr("disabled");
        }
        else {
            $("#btnMakeOrder").attr("class", "button CheckOutButtonInActive")
            $("#btnMakeOrder").attr("disabled", "disabled");
        }
    }

    this.HideSlider = function() {
        $("#pnlSlider").hide();
    }

    this.HideScale = function() {
        $("#pnlScale").hide();
    }

    this.HideMeasureUnits = function() {
        $("#pnlMeasureUnits").hide();
    }

    this.CreateSlider = function() {
        $('#jSlider').slider({
            range: 'max',
            min: 10,
            max: 500,
            step: 10,
            value: 100,
            slide: function(event, ui) {
                onScaleRatioChanging(ScaleRatio.FromPercent(ui.value).ApplyLimit());
            },
            stop: function(event, ui) {
                onScaleRatioChanged(ScaleRatio.FromPercent(ui.value).ApplyLimit());
            }
        });

        $('#txtScaleRatioPercent').change(function() {
            onScaleRatioChanged(ScaleRatio.FromPercent($(this).val()).ApplyLimit());
        });

        $('#txtScaleRatioNumerator').change(function() {
            onScaleRatioChanged(ScaleRatio.FromNumerator($(this).val()).ApplyLimit());
        });

        $('#txtScaleRatioDenominator').change(function() {
            onScaleRatioChanged(ScaleRatio.FromDenominator($(this).val()).ApplyLimit());
        });

        $('#txtScaleRatioPercent,#txtScaleRatioNumerator,#txtScaleRatioDenominator').keypress(function(e) {
            var keyNum;
            var keyChar;
            var numCheck;

            if ($.browser.msie) {
                keyNum = e.keyCode;
            } else {
                keyNum = e.which;
            }
            keyChar = String.fromCharCode(keyNum);
            numCheck = /[\d\.\x08]/;
            if (numCheck.test(keyChar)) {
                if (keyChar == '.' && $(this).val().indexOf('.') >= 0) {
                    return false;
                }
                if ($(this).attr("id") == "txtScaleRatioNumerator") {
                    _View.ScaleRatioDenominator(ScaleRatio.Default().Denominator());
                }
                else if ($(this).attr("id") == "txtScaleRatioDenominator") {
                    _View.ScaleRatioNumerator(ScaleRatio.Default().Numerator());
                }
                return true;
            }
            else if (keyChar == "\n" || keyChar == "\r") {
                //Do this to prevent submitting form on Enter
                var scaleRatio;
                if ($(this).attr("id") == "txtScaleRatioNumerator") {
                    scaleRatio = ScaleRatio.FromNumerator($(this).val()).ApplyLimit();
                }
                else if ($(this).attr("id") == "txtScaleRatioDenominator") {
                    scaleRatio = ScaleRatio.FromDenominator($(this).val()).ApplyLimit();
                }
                else {
                    scaleRatio = ScaleRatio.FromPercent($(this).val()).ApplyLimit();
                }
                onScaleRatioChanged(scaleRatio);
                $(this).blur();
                return false;
            }
            else {
                return false;
            }
        });
    }

    this.CreateSpin = function() {
        $('#txtQuantity').attr("maxlength", 3);
        $('#txtQuantity').change(function() {
            requestPrice();
            $('#txtQuantity').blur();

        });
        $('#txtQuantity').keypress(function(evt) {
            var keyNum;
            var keyChar;
            var numCheck;

            if ($.browser.msie) {
                keyNum = evt.keyCode;
            } else {
                keyNum = evt.which;
            }
            keyChar = String.fromCharCode(keyNum);
            numCheck = /[\d\n\r\x08]/;
            if (numCheck.test(keyChar)) {
                return true;
            } else {
                return false;
            }
        });
        $('#txtQuantity').spin({
            imageBasePath: '/Images/main/',
            spinBtnImage: 'spin-norm.gif',
            spinUpImage: 'spin-up.gif',
            spinDownImage: 'spin-low.gif',
            min: 1,
            max: 999
        });

    }

    this.CreateScrollable = function() {
        $("div.scrollable").scrollable({ size: 5, prev: "div.prev", next: "div.next", loop: true, hoverClass: "hover", clickable: false });
    }

    this.ShowUploadToolTip = function() {
        var tooltipApi = $("#imgUploaderInsert").tooltip({ tip: '.uploadToolTip', api: true });
        if (typeof tooltipApi != "undefined") {
            tooltipApi.show();
            var uplBut = tooltipApi.getTrigger().parent();
            uplBut.mouseover(function() {
                tooltipApi.hide();
                tooltipApi.unbind("mouseover");
            });
        }
    }

    this.FileUploadTime = function(fileUploadTime) {
        if (typeof fileUploadTime != "undefined") {
            $("#hdnFileUploadTime").val(fileUploadTime);
        }
    }
}

function ViewInitializer() {
}

ViewInitializer.prototype.InitView = function(view, model) {
    view.AllowCheckout(false);
    view.InitSlideShow();
    $("#rbtInch").click(function() {
        model.SetConvertToInches(true);
    });
    $("#rbtMM").click(function() {
        model.SetConvertToInches(false);
    });

    $("#rbtInch, #rbtMM").click(function() {
        view.MeasureUnit($(this).val());
        if (model.HasDimensions()) {
            view.Dimensions(model.GetDimX(), model.GetDimY(), model.GetDimZ());
        }
    });

    _View.CreateScrollable();
    _View.CreateSpin();
}

function ViewInitializerNoneToolType() {
}

ViewInitializerNoneToolType.prototype = new ViewInitializer();

ViewInitializerNoneToolType.prototype.InitView = function(view, model) {
    ViewInitializer.prototype.InitView.call(this, view, model);
    view.CreateSlider();
}

function ViewInitializerLampToolType() {
}

ViewInitializerLampToolType.prototype = new ViewInitializer();

ViewInitializerLampToolType.prototype.InitView = function(view, model) {
    ViewInitializer.prototype.InitView.call(this, view, model);
    view.HideScale();
    view.HideSlider();
    view.ShowUploadToolTip();
    view.CreateSlider();
}

function ViewInitializerVaseToolType() {
}

ViewInitializerVaseToolType.prototype = new ViewInitializer();

ViewInitializerVaseToolType.prototype.InitView = function(view, model) {
    ViewInitializer.prototype.InitView.call(this, view, model);
    view.HideSlider();
    view.ShowUploadToolTip();
}

function ViewInitializerArchitecturalModelToolType() {
}

ViewInitializerArchitecturalModelToolType.prototype = new ViewInitializer();

ViewInitializerArchitecturalModelToolType.prototype.InitView = function(view, model) {
    ViewInitializer.prototype.InitView.call(this, view, model);
    view.HideScale();
    view.HideSlider();
    view.HideMeasureUnits();
}

function ViewInitializerBookendToolType() {
}

ViewInitializerBookendToolType.prototype = new ViewInitializer();

ViewInitializerBookendToolType.prototype.InitView = function(view, model) {
    ViewInitializer.prototype.InitView.call(this, view, model);
    view.HideScale();
    view.HideSlider();
    view.QuantityLabel("Number of Sets");
    view.PriceLabel("Set Price");
    view.ShowUploadToolTip();
}


//Static factory method which returns concrete View Initializer
ViewInitializer.GetConcrete = function(toolType) {
    switch (toolType) {
        case ToolType.Vase:
            return new ViewInitializerVaseToolType();
        case ToolType.Lamp:
            return new ViewInitializerLampToolType();
        case ToolType.ArchitecturalModel:
            return new ViewInitializerArchitecturalModelToolType();
        case ToolType.Bookend:
            return new ViewInitializerBookendToolType();
        default:
            return new ViewInitializerNoneToolType();
    }
}

var _Model = new Model();
var _View = new View();

function initPage(toolType) {    
    _Model.SetToolType(toolType);
    ViewInitializer.GetConcrete(toolType).InitView(_View, _Model);
}

function initPageWithModel(modelGuid, quantity, subtotal, dimX, dimY, dimZ, scaleRatio, convertToInches, modelPreviewImg, currencySymbol) {
    state = State.GeneratingPreview;
    _Model.Init(modelGuid, state, subtotal, dimX, dimY, dimZ, new ScaleRatio(scaleRatio), convertToInches);
    _View.Dimensions(_Model.GetDimX(), _Model.GetDimY(), _Model.GetDimZ());
    _View.Quantity(quantity);
    _View.Price(subtotal);
    _View.ScaleRatio(new ScaleRatio(scaleRatio));
    _View.StopSlideShow();
    _View.CurrencySymbol(currencySymbol);

    if (convertToInches) {
        _View.MeasureUnit(MeasureUnit.Inch);
    }
    else {
        _View.MeasureUnit(MeasureUnit.MM);
    }
    $("#modelHold").show();
}

function onChangeMaterial() {
    var selectedVal = _View.SelectedMaterial;
    $.getJSON("/Home/GetFinishings", { 'materialID': selectedVal }, fillCbxFinishings);
}

function fillCbxFinishings(values) {
    _View.Finishings(values);
    onChangeFinishing();
}

function onChangeFinishing() {
    var selectedMaterial = _View.SelectedMaterial;
    var selectedFinishing = _View.SelectedFinishing;
    $.getJSON("/Home/GetColours", { 'materialID': selectedMaterial, 'finishingID': selectedFinishing }, fillCbxColours);
}

function onChangeColour() {
        requestPrice();
}

function fillCbxColours(values) {
    _View.Colours(values);
    requestPrice();
}

function allowSpinChange() {
    return !_View.IsCalculating();
}

function requestPrice() {
    if (_Model.GetModelGuid() != null) {
        _View.SetPriceStatusCalculate();
        var selectedMaterial = _View.SelectedMaterial();
        var selectedFinishing = _View.SelectedFinishing();
        var selectedColour = _View.SelectedColour();
        var selectedScaleRatio = _View.ScaleRatio().Value();
        var quantity = _View.Quantity();
        $.getJSON("/Home/GetPrice", { 'materialID': selectedMaterial, 'finishingID': selectedFinishing, 'colourID': selectedColour, 'scaleRatio': selectedScaleRatio, 'quantity': quantity }, setPrice);
    }
}

function setPrice(priceResult) {
    var result = new ModelProcessingResult(priceResult);
    _Model.SetState(result.GetState());
    _View.HidePriceStatusCalculate();

    if (result.GetState() == State.Succeed) {
        _Model.SetSubtotal(result.GetPrice());
        _View.Price(result.GetPrice());
        _View.CurrencySymbol(result.GetCurrencySymbol());
        _View.AllowCheckout(true);
    }

    updateStatusArea();
}

function onScaleRatioChanging(scaleRatio) {
    _Model.SetScaleRatio(scaleRatio);
    _View.ScaleRatio(scaleRatio);
    if (_Model.HasDimensions()) {
        _View.Dimensions(_Model.GetDimX(), _Model.GetDimY(), _Model.GetDimZ());
    }
}

function onScaleRatioChanged(scaleRatio) {
    onScaleRatioChanging(scaleRatio);
    requestPrice();
}

//Fires when an upload of a specific file has started
function CuteWebUI_AjaxUploader_OnStart() {
    _Model.RememberFileUploadStartTime();

    $("#imgUploaderInsert").before("<div class='statusMsg'> Please select your materialising options on the right panel. As soon as we have processed your file your price will appear.</div>");
    $("#imgUploaderInsert").css("display", "none");
}

function CuteWebUI_AjaxUploader_OnPostback() {
    _View.FileUploadTime(_Model.CalculateFileUploadTime());

    var uploader = document.getElementById("ModelUploader");
    var modelID = uploader.value;

    document.frmOrder.action = "/Home/SaveModel";
    document.frmOrder.submit();
}

function updateStatusArea() {
    $.get("/Model/UpdateStatusArea", null, function(result) {
        $("#StatusArea").html(result);
    });
}

function getModelProcessingState() {
    if (_Model.GetModelGuid() != null) {
        var pollRequest = function() {
            $.getJSON("/Model/Status/" + _Model.GetModelGuid(), getModelProcessingStateCallback);
        };
        setTimeout(pollRequest, 1000);
    }
}

function getModelProcessingStateCallback(data) {
    var result = new ModelProcessingResult(data);

    _Model.SetState(result.GetState());

    if (_Model.GetState() == State.GeneratingPreview) {
        getModelProcessingState();
    }
    else if (_Model.GetState() == State.Fixing) {
        if (_Model.IsStateChanged()) {
            _Model.SetDimensions(result.GetDimX(), result.GetDimY(), result.GetDimZ());
            _View.Dimensions(_Model.GetDimX(), _Model.GetDimY(), _Model.GetDimZ());
            _View.SetPreview(result.GetModelPreviewDescriptor());
        }
        getModelProcessingState();
    }
    else if (_Model.GetState() == State.CalculatingPrice) {
        if (_Model.IsStateChanged()) {
            _Model.SetDimensions(result.GetDimX(), result.GetDimY(), result.GetDimZ());
            _View.Dimensions(_Model.GetDimX(), _Model.GetDimY(), _Model.GetDimZ());
            _View.SetPreview(result.GetModelPreviewDescriptor());
        }
        requestPrice();
    }
    else if (_Model.GetState() == State.CantBeFixed && _Model.IsStateChanged()) {
        _Model.SetDimensions(result.GetDimX(), result.GetDimY(), result.GetDimZ());
        _View.Dimensions(_Model.GetDimX(), _Model.GetDimY(), _Model.GetDimZ());
        _View.SetPreview(result.GetModelPreviewDescriptor());
    }

    if (_Model.IsStateChanged()) {
        updateStatusArea();
    }
}

