﻿MarketRatesDataEngine = function(options) {
    /*
    * Defaults objects
    * @param dataURL - the url the get the json data
    * @param timerDelay - the delay between each requset 
    * @param autoStart - true to statr get requset in instanse creation
    * @param callbacks - array of callbacks to be called on instruent change
    * @param ratesList - array of rates list to be added to each requset
    */
    var defaults =
  {
      baseURL: 'http://webrates2.leverate.com/MarketRates/',
      initAction: 'Init',
      getDataAction: 'GetData',
      timerDelay: 15000,
      autoStart: false,
      clientID: null,
      callbacks: [],
      initCallbacks: [],
      ratesList: []
  }

    //public Market Rate Status enum
    var marketRateStatus =
  {
      noChange: 0,
      up: 1,
      down: 2
  };

    //private data members
    var base,
      config,
      lastServerTime,
      ratesListAsString,
      oldRatesData,
      isActive = false;

    /*
    * Public set rates list in array format
    * @param ratesList  - rates list to replace 
    */
    setRatesList = function(ratesList) {
        config.ratesList = ratesList;
        ratesListAsString = ratesList.join(',');
    };

    /*
    * Public add rates list in to exsisting list in array format
    * @param ratesList  - rates list to add 
    */
    addRatesList = function(ratesList) {
        config.ratesList = $.extend(config.ratesList, ratesList);
        ratesListAsString = config.ratesList.join(',');
    };

    /*
    * Public add callback function to be fired on instrument change
    * @param func  - the function will be called with the following params
    * rowData - the data of the new instrument 
    * bidRateStatus - the enum indecaties the status of the bid rate 
    * askRateStatus - the enum indecaties the status of the ask rate,
    * oldRateData - the previous instrument data
    *  
    */
    addCallback = function(func) {
        config.callbacks.push(func)
    };

    addInitCallback = function(func) {
        config.initCallbacks.push(func)
    };

    /*
    * Public  Start the data engine to requesting data from the server
    */
    start = function() {
        if (!isActive) {
            isActive = true;
            getInitData();
        }
    };

    /*                                 
    * Public  Stop the data engine from requesting data from the server
    */
    stop = function() {
        isActive = false;
    };

    getInitData = function() {
        $.ajax({
            type: "GET",
            url: config.baseURL + config.initAction,
            data: { clientID: config.clientID, style: config.style },
            success: getInitDataCallback,
            dataType: 'jsonp'
        });
    };

    getInitDataCallback = function(result) {
        if (result.success) {
            $.each(config.initCallbacks, function() {
                this(result.Data);
            });

            getData();
        }
    };

    /*
    * Fetch json rates data from the setver , send the last server time the each requset
    */
    var getData = function() {
        $.ajax({
            type: "GET",
            url: config.baseURL + config.getDataAction,
            data: { lastServerTime: lastServerTime, crosses: ratesListAsString },
            success: getDataCallback,
            dataType: 'jsonp'
        });
    }

    /*
    * Json data return callback
    * read new data form the server and update the table
    */
    var getDataCallback = function(result) {
        if (result.success) {
            //set last server time for the next requset;
            lastServerTime = result.Data.ServerTime;

            //handle each instrument needed to update
            $.each(result.Data.InstrumentRates, function() {
                handleRowUpdate(this);
            });

            //set timeout the call the next rates update
            if (isActive) {
                setTimeout(getData, config.timerDelay);
            }
        }
    }

    /*
    * handle each row update by checking if the data was changed and fire the callback functions
    */
    var handleRowUpdate = function(rowData) {
        //prepare working data
        var oldRateData = oldRatesData[rowData.InstrumentName],
	      bidRateStatus = marketRateStatus.noChange,
	      askRateStatus = marketRateStatus.noChange;

        //check if we have valid old data object
        if (oldRateData == null) {
            oldRateData =
      {
          BidRate: Number.MIN_VALUE,
          AskRate: Number.MIN_VALUE
      }
        }

        //update the status of the bid rate
        if (oldRateData.BidRate !== rowData.BidRate) {
            bidRateStatus = oldRateData.BidRate < rowData.BidRate ? marketRateStatus.up : marketRateStatus.down;
        }
        //update the status of the ask rate
        if (oldRateData.AskRate !== rowData.AskRate) {
            askRateStatus = oldRateData.AskRate < rowData.AskRate ? marketRateStatus.up : marketRateStatus.down
        }

        //chekc if we hand a change in one of the rates and fire the callback functions
        if (bidRateStatus !== marketRateStatus.noChange || askRateStatus !== marketRateStatus.noChange) {
            $.each(config.callbacks, function() {
                this(rowData, bidRateStatus, askRateStatus, oldRateData);
            });
        }

        //update the old data by instrument name
        oldRatesData[rowData.InstrumentName] = rowData;
    }

    init = function() {
        // To avoid scope issues, use 'base' instead of 'this'
        base = this;

        // Extend config with defults and options passed from the user 
        config = $.extend({}, defaults, options);

        //init last date
        lastServerTime = null;

        oldRatesData = [];
        setRatesList(config.ratesList)

        //get init data
        if (config.autoStart) {
            start()
        }
    }

    //make public functions
    this.setRatesList = setRatesList;
    this.addRatesList = addRatesList;
    this.addCallback = addCallback;
    this.addInitCallback = addInitCallback;
    this.start = start;
    this.stop = stop;
    this.marketRateStatus = marketRateStatus;

    init();
};


