﻿/// <reference name="MicrosoftAjax.js"/>

Type.registerNamespace("BOK");

BOK.client_cost_calc = function(element) {
    // Constants
    this._taxPercentages = 0.3;
    this._totalBusinessHoursPerYearWorkstation = 2000;
    this._totalBusinessHoursPerYearServer = 3132;
    this._totalHoursPerYear = 8760;
    this._estUpTimeBestCase = 0.99;
    this._costOfServiceMonthServer = 195;
    this._costOfServiceMonthDesktop = 40;
    this._costOfServiceYearServer = 2340;
    this._costOFServiceYearDesktop = 480;

    // Private Variables
    this._averageSalary = 0;
    this._averageRevenue = 0;

    this._events = null;

    BOK.client_cost_calc.initializeBase(this, [element]);
}

BOK.client_cost_calc.prototype = {
    // Init
    initialize: function() {
        BOK.client_cost_calc.callBaseMethod(this, 'initialize');

        if (this._roi == "") {
            this._roi = 0;
        }

        if (this._estPrice == "") {
            this._estPrice = 0;
        }

        if (this._estPrice == "") {
            this._totalCostBeingSpent = 0;
        }

        // Event Handlers
        $addHandlers(this._numberOfServersElement,
        {
            change: this.Update
        }, this);

        $addHandlers(this._numberOfEmployeesElement,
        {
            change: this.Update
        }, this);

        $addHandlers(this._averageStaffSalaryElement,
        {
            change: this.Update
        }, this);

        $addHandlers(this._averageAnnualRevenueElement,
        {
            change: this.Update,
            'keyup': this.Update
        }, this);

        $addHandlers(this._productivityPerHourElement,
        {
            change: this.Update
        }, this);
    },

    // Dispose
    dispose: function() {
        $clearHandlers(this._numberOfServersElement);
        $clearHandlers(this._numberOfEmployeesElement);
        $clearHandlers(this._averageStaffSalaryElement);
        $clearHandlers(this._averageAnnualRevenueElement);
        $clearHandlers(this._productivityPerHourElement);

        BOK.client_cost_calc.callBaseMethod(this, 'dispose');
    },

    _load: function() {
        this.Update();
    },

    // Private Methods
    get_TaxBenefits: function() {

        if (isNaN(this._averageSalary)) {
            return 0;
        }
        else {
            return this._averageSalary * this._taxPercentages;
        }
    },

    get_EmployeeCost: function() {
        var returnValue = 0;
        returnValue = (this._averageSalary + this.get_TaxBenefits()) / 2080;

        if (isNaN(returnValue)) {
            return 0;
        }
        else {
            return returnValue;
        }
    },

    get_ProductivityPerHour: function() {
        var returnValue = 0;
        returnValue = (this._averageRevenue / parseInt(this._numberOfEmployeesElement.value)) / this._totalBusinessHoursPerYearWorkstation;

        if (isNaN(returnValue)) {
            return 0;
        }
        else {
            return returnValue;
        }
    },

    get_estSelectedUptime: function(uptimeBestCase, totalHours) {
        return uptimeBestCase * totalHours;
    },

    get_totalOutage: function(totalHours, selectedUptime) {
        return totalHours - selectedUptime;
    },

    get_PercentageForBusinessHour: function(totalBusinessHours, totalHours) {
        return (totalBusinessHours / totalHours) * 100;
    },

    get_PercentageOutageBusinessHour: function(percentageBusinessHours, totalOutage) {
        return (percentageBusinessHours * totalOutage) / 100;
    },

    get_ExpectedOutageHours: function(totalOutage, perHour) {
        return (totalOutage * perHour) / 100;
    },

    get_LostServerHours: function(avgOutage) {
        var returnVal = parseInt(parseInt(this._numberOfEmployeesElement.value) * avgOutage);

        if (isNaN(returnVal)) {
            return 0;
        } else {
            return returnVal;
        }
    },

    get_roundNumber: function(number, decimalPlace) {
        var result = Math.round(number * Math.pow(10, decimalPlace)) / Math.pow(10, decimalPlace);
        return result;
    },

    // Event Handlers
    Update: function() {
        this._averageSalary = parseInt(this._averageStaffSalaryElement.value.toString().replace(/,/g, ""));
        this._averageRevenue = parseInt(this._averageAnnualRevenueElement.value.replace(/,/g, ""));

        var employeeCostPerHour = this.get_EmployeeCost();
        var productivityPerHour = this.get_ProductivityPerHour();

        var estSelectedUptimeServer = this.get_estSelectedUptime(this._estUpTimeBestCase, this._totalHoursPerYear);
        var estSelectedUptimeWorkstation = this.get_estSelectedUptime(this._estUpTimeBestCase, this._totalHoursPerYear);

        var estTotalOutageServer = this.get_totalOutage(this._totalHoursPerYear, estSelectedUptimeServer);
        var estTotalOutageWorkstation = this.get_totalOutage(this._totalHoursPerYear, estSelectedUptimeWorkstation);

        var estPerBusinessHoursServer = this.get_PercentageForBusinessHour(this._totalBusinessHoursPerYearServer, this._totalHoursPerYear);
        var estPerBusinessHoursWorkstation = this.get_PercentageForBusinessHour(this._totalBusinessHoursPerYearWorkstation, this._totalHoursPerYear);

        var estPerBusinessOutageHoursServer = this.get_PercentageOutageBusinessHour(estPerBusinessHoursServer, estTotalOutageServer);
        var estPerBusinessOutageHoursWorkstation = this.get_PercentageOutageBusinessHour(estPerBusinessHoursWorkstation, estTotalOutageWorkstation);

        var avgOutageServer = this.get_roundNumber((estTotalOutageServer * estPerBusinessOutageHoursServer) / 100, 2);
        var avgOutageDesktop = this.get_roundNumber((estTotalOutageWorkstation * estPerBusinessOutageHoursWorkstation) / 100, 2);

        var hoursLostServer = this.get_LostServerHours(avgOutageServer);
        var hoursLostDesktop = avgOutageDesktop;

        var hoursCatchingUpServer = this.get_roundNumber(hoursLostServer / 2, 0);
        var hoursCatchingUpDesktop = this.get_roundNumber(hoursLostDesktop / 2, 0);

        var totalProductivityHoursLostServer = hoursCatchingUpServer + hoursLostServer;

        // Rounding here would make the numbers greater, but messes up the example.  So I'm going to parse instead of round
        var totalProductivityHoursLostDesktop = parseInt(hoursCatchingUpDesktop + hoursLostDesktop);

        var costOfIdleTimeServer = employeeCostPerHour * totalProductivityHoursLostServer;
        var costOfIdleTimeDesktop = employeeCostPerHour * totalProductivityHoursLostDesktop;

        var estOpportunityCostServer = productivityPerHour * totalProductivityHoursLostServer;
        var estOpportunityCostDesktop = productivityPerHour * totalProductivityHoursLostDesktop;

        var totalLostCostServer = costOfIdleTimeServer + estOpportunityCostServer;
        var totalLostCostDesktop = costOfIdleTimeDesktop + estOpportunityCostDesktop;

        var costOfRepairServer = 125 * (.75 * avgOutageServer);
        var costOfRepairDesktop = 110 * (.5 * avgOutageDesktop);

        var totalCostOfDownTimeServer = totalLostCostServer + costOfRepairServer;
        var totalCostOfDownTimeDesktop = totalLostCostDesktop + costOfRepairDesktop;

        var costUnderContractServer = this._costOfServiceYearServer * this._numberOfServersElement.value;
        var costUnderContractDesktop = this._costOFServiceYearDesktop * this._numberOfEmployeesElement.value;

        var totalCostToday = totalCostOfDownTimeServer + totalCostOfDownTimeDesktop;
        var estCompleteNetwork = (this._costOfServiceYearServer * this._numberOfServersElement.value) + (this._costOFServiceYearDesktop * this._numberOfEmployeesElement.value);
        var roi = (totalCostToday - estCompleteNetwork) / estCompleteNetwork

        this._taxBenefitsElement.innerHTML = String.localeFormat("{0:c}", this.get_TaxBenefits());
        this._employeeCostPerHourElement.innerHTML = String.localeFormat("{0:c}", employeeCostPerHour);
        this._productivityPerHourElement.innerHTML = String.localeFormat("{0:c}", productivityPerHour);

        this._averageOutageServerElement.innerHTML = avgOutageServer;
        this._averageOutageDesktopElement.innerHTML = avgOutageDesktop;

        this._hourLostServerElement.innerHTML = hoursLostServer;
        this._hoursLostDesktopElement.innerHTML = hoursLostDesktop;

        this._hourLostCatchingUpServerElement.innerHTML = hoursCatchingUpServer;
        this._hourLostCatchingUpDesktopElement.innerHTML = hoursCatchingUpDesktop;

        this._totalProductivityHoursLostServerElement.innerHTML = totalProductivityHoursLostServer;
        this._totalProductivityHoursLostDesktopElement.innerHTML = totalProductivityHoursLostDesktop;

        this._averageHourlyWageServerElement.innerHTML = this._employeeCostPerHourElement.innerHTML;
        this._averageHourlyWageDesktopElement.innerHTML = this._employeeCostPerHourElement.innerHTML;

        this._costOfEmployeeIdleTimeServerElement.innerHTML = String.localeFormat("{0:c}", this.get_roundNumber(costOfIdleTimeServer, 0));
        this._costOfEmployeeIdleTimeDesktopElement.innerHTML = String.localeFormat("{0:c}", this.get_roundNumber(costOfIdleTimeDesktop, 0));

        this._estOpportunityCostServerElement.innerHTML = String.localeFormat("{0:c}", this.get_roundNumber(estOpportunityCostServer, 0));
        this._estOpportunityCostDesktopElement.innerHTML = String.localeFormat("{0:c}", this.get_roundNumber(estOpportunityCostDesktop, 0));

        this._totalLostCostServerElement.innerHTML = String.localeFormat("{0:c}", this.get_roundNumber(totalLostCostServer, 0));
        this._totalLostCostDesktopElement.innerHTML = String.localeFormat("{0:c}", this.get_roundNumber(totalLostCostDesktop, 0));

        this._costOfRepairServerElement.innerHTML = String.localeFormat("{0:c}", this.get_roundNumber(costOfRepairServer, 0));
        this._costOfRepairDesktopElement.innerHTML = String.localeFormat("{0:c}", this.get_roundNumber(costOfRepairDesktop, 0));

        this._totalCostDownTimeServerElement.innerHTML = String.localeFormat("{0:c}", this.get_roundNumber(totalCostOfDownTimeServer, 0));
        this._totalCostDownTimeDesktopElement.innerHTML = String.localeFormat("{0:c}", this.get_roundNumber(totalCostOfDownTimeDesktop, 0));

        //this._costOfServiceYearServerElement.innerHTML = this._costOfServiceYearServer;
        //this._costOfServiceYearDesktopElement.innerHTML = this._costOFServiceYearDesktop;
        //this._costOfServiceMonthServerElement.innerHTML = this._costOfServiceMonthServer;
        //this._costOfServiceMonthDesktopElement.innerHTML = this._costOfServiceMonthDesktop;

        this._posUnderContractServerElement.innerHTML = this.get_roundNumber(totalCostOfDownTimeServer / this._costOfServiceYearServer, 0);
        this._posUnderContractDesktopElement.innerHTML = this.get_roundNumber(totalCostOfDownTimeDesktop / this._costOFServiceYearDesktop, 0);

        //this._costManageAllServerElement.innerHTML = String.localeFormat("{0:c}", this.get_roundNumber(costUnderContractServer, 0));
        //this._costManageAllDesktopElement.innerHTML = String.localeFormat("{0:c}", this.get_roundNumber(costUnderContractDesktop, 0));

        this._breakEvenServerElement.innerHTML = this.get_roundNumber(costUnderContractServer / costOfRepairServer, 1);
        this._breakEvenDesktopElement.innerHTML = this.get_roundNumber(costUnderContractDesktop / costOfRepairDesktop, 1);

        this._totalCostBeingSpent = this.get_roundNumber(totalCostToday, 0);
        this._estPrice = this.get_roundNumber(estCompleteNetwork, 0);
        this._roi = roi;

        this._raiseEvent("Updated");
    }
}

BOK.client_cost_calc.createProperty("numberOfServersElement");
BOK.client_cost_calc.createProperty("numberOfEmployeesElement");
BOK.client_cost_calc.createProperty("averageStaffSalaryElement");
BOK.client_cost_calc.createProperty("taxBenefitsElement");
BOK.client_cost_calc.createProperty("employeeCostPerHourElement");
BOK.client_cost_calc.createProperty("averageAnnualRevenueElement");
BOK.client_cost_calc.createProperty("productivityPerHourElement");
BOK.client_cost_calc.createProperty("averageOutageServerElement");
BOK.client_cost_calc.createProperty("averageOutageDesktopElement");
BOK.client_cost_calc.createProperty("hourLostServerElement");
BOK.client_cost_calc.createProperty("hoursLostDesktopElement");
BOK.client_cost_calc.createProperty("hourLostCatchingUpServerElement");
BOK.client_cost_calc.createProperty("hourLostCatchingUpDesktopElement");
BOK.client_cost_calc.createProperty("totalProductivityHoursLostServerElement");
BOK.client_cost_calc.createProperty("totalProductivityHoursLostDesktopElement");
BOK.client_cost_calc.createProperty("averageHourlyWageServerElement");
BOK.client_cost_calc.createProperty("averageHourlyWageDesktopElement");
BOK.client_cost_calc.createProperty("costOfEmployeeIdleTimeServerElement");
BOK.client_cost_calc.createProperty("costOfEmployeeIdleTimeDesktopElement");
BOK.client_cost_calc.createProperty("estOpportunityCostServerElement");
BOK.client_cost_calc.createProperty("estOpportunityCostDesktopElement");
BOK.client_cost_calc.createProperty("totalLostCostServerElement");
BOK.client_cost_calc.createProperty("totalLostCostDesktopElement");
BOK.client_cost_calc.createProperty("costOfRepairServerElement");
BOK.client_cost_calc.createProperty("costOfRepairDesktopElement");
BOK.client_cost_calc.createProperty("totalCostDownTimeServerElement");
BOK.client_cost_calc.createProperty("totalCostDownTimeDesktopElement");
BOK.client_cost_calc.createProperty("posUnderContractServerElement");
BOK.client_cost_calc.createProperty("posUnderContractDesktopElement");
BOK.client_cost_calc.createProperty("breakEvenServerElement");
BOK.client_cost_calc.createProperty("breakEvenDesktopElement");
BOK.client_cost_calc.createProperty("totalCostBeingSpent");
BOK.client_cost_calc.createProperty("estPrice");
BOK.client_cost_calc.createProperty("roi");

BOK.client_cost_calc.createEvent("Updated");

BOK.client_cost_calc.registerClass('BOK.client_cost_calc', Sys.UI.Control);

if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();