var _sliders = {
  sliders: [],
  get: function(id){
    id = 'slider_' + id;
    var key;
    for (key in this.sliders){
      if (id == key){
        return this.sliders[key];
      }
    }
  },
  add: function(id, slider){
    id = 'slider_' + id;
    this.sliders[id] = slider;
  }
};

function _buy(id, name, use_modal_title)
{
  if (use_modal_title) {
    var title = Modalbox.options.title;
  } else {
	  if (!name) {
	    var title = 'Buy Stock';
	  } else {
	    var title = 'Buy ' + name;
	  }
	}
  var url = _buy_url + '?id=' + id;
  _doBuySell(url, title);
}
function _sell(id, name, use_modal_title)
{
  if (use_modal_title) {
    var title = Modalbox.options.title;
  } else {
	  if (!name) {
	    var title = 'Sell Stock';
	  } else {
	    var title = 'Sell ' + name;
	  }
	}
  var url = _sell_url + '?id=' + id;
  _doBuySell(url, title);
}
function _doBuySell(url, title)
{
  if (!Object.isUndefined(_refresh_allowed) && _refresh_allowed)
  {
    url += '&r=' + _refresh_to;
  }
  Modalbox.show(url, {
    autoFocusing: false,
    title: title,
    width: 605,
    //height: 212,
    overlayOpacity: 0.8,
    overlayDuration: 0,
    slideDownDuration: 0.1,
    slideUpDuration: 0.1,
    //resizeDuration: 0.1,
    afterLoad: function() {try{_initTransactionBox($('id_prefix').getValue());}catch(e){}},
    method: 'post'
    });
}
function _initTransactionBox(id_prefix) {
  var id_prefix = (!id_prefix ? '' : String(id_prefix));
  $(id_prefix + 'num_shares').setValue(0);
  $(id_prefix + 'processing').setValue(0);
  var max_shares = _toInt($(id_prefix + 'max_shares').innerHTML.replace(/[^0-9]/g, ''));
  var slider = new Control.Slider(id_prefix + 'handle',id_prefix + 'track', {
      range:$R(0,max_shares),
      sliderValue: 0,
      id_prefix: id_prefix,
      //values:[0,25,50,100],
      onChange:function(v){
          $(this.id_prefix + 'num_shares').setValue(_toInt(v));
          _updateTransactionSpace(id_prefix, true);
        },
      onSlide:function(v){
          $(this.id_prefix + 'num_shares').setValue(_toInt(v));
          _updateTransactionSpace(id_prefix, true);
        }
      }
    );
  _sliders.add(id_prefix, slider);
  _updateTransactionSpace(id_prefix);
}
function _updateTransactionSpace(id_prefix, slider_updated)
{
  slider_updated = (!slider_updated ? false : true);
  var id_prefix = (!id_prefix ? '' : String(id_prefix));
  var transaction_type = (String($(id_prefix + 'transaction_type').getValue()).valueOf() == String('sell').valueOf() ? 'sell' : 'buy');
  _normaliseTransactionNumUnitsInput(id_prefix);
  var num_shares = _toInt($(id_prefix + 'num_shares').getValue());
  var cost_per_share = _toFloat($(id_prefix + 'cost_per_share').innerHTML);
  var total_cost = (num_shares * (1000 * cost_per_share))/1000;
  $(id_prefix + 'total_cost').innerHTML = _number_format(total_cost, 3);
  var cash = _toFloat($(id_prefix + 'cash_before').getValue());
  var cash_after_transaction = (transaction_type == 'buy' ? ((1000*cash)-(1000*total_cost))/1000 : ((1000*cash)+(1000*total_cost))/1000);
  $(id_prefix + 'cash_after_transaction').innerHTML = _number_format(cash_after_transaction, 3);
  if (!slider_updated)
  {
    _sliders.get(id_prefix).setValue(num_shares);
  }
  if (transaction_type == 'sell')
  {
    var real_price = _toFloat($(id_prefix + 'real_price').innerHTML);
    var seller_fee = _toFloat($(id_prefix + 'seller_fee').innerHTML);
    var average_purchase_price = _toFloat($(id_prefix + 'average_purchase_price').innerHTML);
    var total_value = (num_shares * (1000 * real_price))/1000;
    var total_seller_fee = (num_shares * (1000 * seller_fee))/1000;
    var total_bought_at = (num_shares * (1000 * average_purchase_price))/1000;
    var total_gain = ((total_value * 1000) - (total_bought_at * 1000))/1000;
    if (total_gain < 0)
    {
      total_gain = ((1000*total_gain)*-1)/1000;
    }
    total_profit = ((total_cost * 1000) - (total_bought_at * 1000))/1000;
    if (total_profit < 0)
    {
      total_profit = ((1000*total_profit)*-1)/1000;
    }
    $(id_prefix + 'total_value').innerHTML = _number_format(total_value, 3);
    $(id_prefix + 'total_seller_fee').innerHTML = _number_format(total_seller_fee, 3);
    $(id_prefix + 'total_cost2').innerHTML = _number_format(total_cost, 3);
    $(id_prefix + 'total_bought_at').innerHTML = _number_format(total_bought_at, 3);
    $(id_prefix + 'total_gain').innerHTML = _number_format(total_gain, 3);
    $(id_prefix + 'total_profit').innerHTML = _number_format(total_profit, 3);
  }
}
function _normaliseTransactionNumUnitsInput(id_prefix)
{
  var id_prefix = (!id_prefix ? '' : String(id_prefix));
  var value = $(id_prefix + 'num_shares').getValue();
  var parsed = value.replace(/[^0-9]/g, '');
  if (String(value).valueOf() != String(parsed).valueOf())
  {
    $(id_prefix + 'num_shares').setValue(parsed);
  }
  var max_shares = _toInt($(id_prefix + 'max_shares').innerHTML.replace(/[^0-9]/g, ''));
  var num_shares = _toInt(parsed);
  if (num_shares > max_shares)
  {
    $(id_prefix + 'num_shares').setValue(max_shares);
  }  
}

function _endTransaction(transaction_type, id_prefix)
{
  Modalbox.hide();
}

function _executeTransaction(transaction_type, id_prefix)
{
  var id_prefix = (!id_prefix ? '' : String(id_prefix));
  var processing = _toInt($(id_prefix + 'processing').getValue());
  if (processing != 0) {
    return processing;
  }
  $(id_prefix + 'processing').setValue(1);
  transaction_type = (String(transaction_type).valueOf() == String('sell').valueOf() ? 'sell' : 'buy');
  _normaliseTransactionNumUnitsInput(id_prefix);
  var num_shares = _toInt($(id_prefix + 'num_shares').getValue());
  if (num_shares <= 0) {
    $(id_prefix + 'processing').setValue(0);
    $(id_prefix + 'error_message').innerHTML = 'Invalid quantity!';
    $(id_prefix + 'general_message').hide();
    $(id_prefix + 'processing_container2').hide();
    $(id_prefix + 'error_message').show();
    return 456;
  }
  var confirm_text = 'Please confirm the following transaction:\n\n\n';
  var action1, action2, action3;
  switch (transaction_type) {
    case 'sell':
      action1 = 'Sell';
      action2 = 'Cash gained';
      action3 = 'Total cash';
      break;
    default:
    case 'buy':
      action1 = 'Buy';
      action2 = 'Cost';
      action3 = 'Cash after transaction';
      break;
  }
  confirm_text += action1 + ': ' + _number_format(num_shares, 0) + ' share' + (num_shares > 1 ? 's' : '') + ' @ $' + _toFloat($(id_prefix + 'cost_per_share').innerHTML) + ' per share\n\n';
  confirm_text += action2 + ': $' + $(id_prefix + 'total_cost').innerHTML + '\n\n';
  confirm_text += action3 + ': $' + $(id_prefix + 'cash_after_transaction').innerHTML + '\n ';

  if (confirm(confirm_text))
  {
    var parameters = $(id_prefix + 'transaction_form').serialize(true);

    $(id_prefix + 'stock_quote_key').setValue('');

    $(id_prefix + 'buy_and_cancel_buttons_space').hide();
    $(id_prefix + 'close_button_space').show();

    $(id_prefix + 'error_message').hide();
    $(id_prefix + 'general_message').hide();
    $(id_prefix + 'processing_container2').show();
    url = (transaction_type == 'sell' ? _sell_commit_url : _buy_commit_url);
    //alert(url);
    new Ajax.Request(url,
      {
        id_prefix: id_prefix,
        method: 'post',
        onSuccess: function(transport, json){
          if (!transport) {
            alert('Received no response from server (transport empty)!');
            return;
          }
          try {
            var response = eval('(' + transport.responseText + ')');
          } catch (e) {
            alert('Error retrieving well-formed info from the server!\n\nError: ' + e + '\n\nResponse:\n' + transport.responseText);
            return;
          }
          _doGeneralServerResponseParse(response);
          $(id_prefix + 'close_button').disabled = false;
          if (!response.ok) {
            if (response.has_errors) {
              $(response.id_prefix + 'error_message').innerHTML = 'ERROR: ';
             var pre = (response.errors.length <= 2 ? '<br />' : '');
             for (var i=0, len=response.errors.length; i<len; i++){
               $(response.id_prefix + 'error_message').innerHTML += pre + response.errors[i];
               pre = '<br>';
             }
           }
           $(response.id_prefix + 'processing_container2').hide();
           $(response.id_prefix + 'general_message').hide();
           $(response.id_prefix + 'error_message').show();
          } else {
            if (response.has_messages){
              $(response.id_prefix + 'general_message').innerHTML = '';
              var pre = (response.messages.length <= 2 ? '<br />' : '');
              for (var i=0, len=response.messages.length; i<len; i++){
                $(response.id_prefix + 'general_message').innerHTML += pre + response.messages[i];
                pre = '<br>';
              }
              $(response.id_prefix + 'processing_container2').hide();
              $(response.id_prefix + 'error_message').hide();
              $(response.id_prefix + 'general_message').show();
            } else {
              $(response.id_prefix + 'processing_container2').hide();
            }
          }
          if (!Object.isUndefined(response.refresh_page) && response.refresh_page)
          {
            switch (true)
            {
            case (Object.isUndefined(response.refresh_using_timestamp) || response.refresh_using_timestamp):
              var regex = /r=[0-9]+/g;
              var l = window.location;
              if (regex.test(window.location.search))
              {
                var new_l = l.protocol + '//' + l.hostname + l.pathname + l.search.replace(regex, 'r=' + response.refresh_time) + l.hash;
                window.location = new_l;
              } else {
                var new_l = l.protocol + '//' + l.hostname + l.pathname + l.search + (l.search.length > 0 ? '&' : '?') + 'r=' + response.refresh_time + l.hash;
                window.location = new_l;
              }
              break;
            default:
            case (!Object.isUndefined(response.refresh_using_self_location) && response.refresh_using_self_location):
              window.location = self.location;
              break;
            case (!Object.isUndefined(response.refresh_using_window_location) && response.refresh_using_window_location):
              window.location = window.location;
              break;
            }
          }
        },
        onFailure: function(e){ alert('Something went wrong...\n' + (e ? e : '')) },
        asynchronous: true,
        evalScripts: false,
        parameters: parameters
    });
  } else {
    $(id_prefix + 'processing').setValue(0);
  }
}






function _doGeneralServerResponseParse(response) {
  try {
    if (response._update_ajax_writables && response._ajax_writables.length) {
      var ajw_prefix = (typeof _ajax_writable_class_name_prefix != 'undefined' ? _ajax_writable_class_name_prefix : '_aj_wr');
      var w = response._ajax_writables;
      var e = document.getElementsByClassName(ajw_prefix);
      var matches;
      for (var i=0,len=e.length; i<len; i++){
        for (var j=0,len2=w.length; j<len2; j++) {
          matches = e[i].getElementsByClassName(w[j].class_name);
          for (var k=0,len3=matches.length; k<len3; k++) {
            matches[k].innerHTML = w[j].content;
          }
        }
      }
    }
  } catch (e) {
  }
}

function _toFloat(value) {
  if (isNaN(parseFloat(String(value).replace(/,/g, ''))))
  {
    return 0;
  }
  return parseFloat(String(value).replace(/,/g, ''));
}

function _toInt(value) {
  if (isNaN(parseInt(String(value).replace(/,/g, ''))))
  {
    return 0;
  }
  return parseInt(String(value).replace(/,/g, ''));
}

function _number_format( number, decimals, dec_point, thousands_sep ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     bugfix by: Michael White (http://getsprink.com)
    // +     bugfix by: Benjamin Lupton
    // +     bugfix by: Allan Jensen (http://www.winternet.no)
    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +     bugfix by: Howard Yeend
    // *     example 1: number_format(1234.5678, 2, '.', '');
    // *     returns 1: 1234.57     

    var n = number, c = isNaN(decimals = Math.abs(decimals)) ? 2 : decimals;
    var d = dec_point == undefined ? "." : dec_point;
    var t = thousands_sep == undefined ? "," : thousands_sep, s = n < 0 ? "-" : "";
    var i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", j = (j = i.length) > 3 ? j % 3 : 0;

    return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
}
function _in_array(needle, haystack, argStrict) {
  // Checks if the given value exists in the array  
  // 
  // version: 903.1614
  // discuss at: http://phpjs.org/functions/in_array
  // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // *     example 1: in_array('van', ['Kevin', 'van', 'Zonneveld']);
  // *     returns 1: true
  var found = false, key, strict = !!argStrict;

  for (key in haystack) {
      if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) {
          found = true;
          break;
      }
  }

  return found;
}

var _bottomExtras = {
  container_element_id: 'bottom_extras_container',
  element_id: 'bottom_extras',
  is_shown: false,
  children_active_status: [],
  flash_is_active: false,
  init: function()
  {
    this.children_active_status['compare_stocks'] = false;
  },
  showBlock: function()
  {
    this.flash();
    Effect.BlindDown(this.container_element_id,{duration:0.2});
  },
  flash: function()
  {
    if (!this.flash_is_active)
    {
      this.flash_is_active = true;
      var flash_duration_milliseconds = 500;
      var flash_duration_seconds = flash_duration_milliseconds/1000;
      new Effect.Highlight(this.element_id,{duration:flash_duration_seconds,startcolor:"#ccccff",endcolor:"#f1f1ff",restorecolor:"#f1f1ff"});
      window.setTimeout("_bottomExtras.flash_is_active=false;",flash_duration_milliseconds);
    }
  },
  hideBlock: function()
  {
    Effect.BlindUp(this.container_element_id,{duration:0.2});
  },
  redraw: function()
  {
    var show = false;
    show = (show || this.children_active_status['compare_stocks']);
    if (show)
    {
      if (!this.is_shown)
      {
        this.is_shown = true;
        this.showBlock();
      }
    } else {
      this.is_shown = false;
      this.hideBlock();
    }
  },
  markActiveStatus: function(id,active)
  {
    this.children_active_status[id] = active;
  }
};

var _compareStocks = {
  base_ajax_url: '/user/compareStocksAjax/',
  stock_ids: [],
  is_minimised: false,
  show: function(show)
  {
    _bottomExtras.markActiveStatus('compare_stocks', show);
    if (show)
    {
      $('compare_stocks_container').show();
      $('compare_stocks_go_container').show();
    } else {
      $('compare_stocks_container').hide();
    }
    _bottomExtras.redraw();
  },
  flash: function()
  {
    _bottomExtras.flash();
  },
  clearAll: function()
  {
    this.show(false);
    $('compare_stocks_loading').show();
    $('compare_stocks_loading2').show();
    var now = new Date();
    var that = this;
    new Ajax.Request(this.base_ajax_url,{
      method: 'POST',
      parameters: 'do=clearall&timestamp='+now.getTime(),
      onSuccess: function(json_response)
      {
        json_response_object = json_response.responseText.evalJSON();
        var response = {responseText: json_response_object.responseText};
        var json = json_response_object.json;
        
        if (json.eval_before_exists)
        {
          eval(json.eval_before);
        }
        $('compare_stocks_loading').hide();
        $('compare_stocks_loading2').hide();
        if (json.ok)
        {
          if (json.replace_stocks_list)
          {
            $('compare_stocks_list').innerHTML = response.responseText;
          }
        } else {
          if (json.alert_error)
          {
            alert(json.error);
          }
        }
        if (json.eval_after_exists)
        {
          eval(json.eval_after);
        }
      }
    });
  },
  addStockByStockId: function(stock_id, remove)
  {
    var adding = true;
    if (arguments.length > 1)
    {
      adding = (arguments[1] ? false : true);
    }
    if (adding)
    {
      this.flash();
      this.show(true);
    }
    if ((adding && !_in_array(stock_id, this.stock_ids)) || (!adding && _in_array(stock_id, this.stock_ids)))
    {
      $('compare_stocks_loading').show();
      $('compare_stocks_loading2').show();
      var now = new Date();
      var that = this;
      new Ajax.Request(this.base_ajax_url,{
        method: 'GET',
        parameters: 'do='+(adding?'add':'remove')+'&stock_id='+stock_id+'&timestamp='+now.getTime(),
        onSuccess: function(json_response)
        {
          json_response_object = json_response.responseText.evalJSON();
          var response = {responseText: json_response_object.responseText};
          var json = json_response_object.json;
          
          if (json.eval_before_exists)
          {
            eval(json.eval_before);
          }
          $('compare_stocks_loading').hide();
          $('compare_stocks_loading2').hide();
          if (json.ok)
          {
            if (json.replace_stocks_list)
            {
              $('compare_stocks_list').innerHTML = response.responseText;
            }
          } else {
            if (json.alert_error)
            {
              alert(json.error);
            }
          }
          that.redraw();
          if (json.eval_after_exists)
          {
            eval(json.eval_after);
          }
        }
      });
    }
  },
  removeStockByStockId: function(stock_id)
  {
    return this.addStockByStockId(stock_id, true);
  },
  redrawMinimised: function()
  {
    if (this.is_minimised)
    {
      $('compare_stocks_row1').hide();
      $('compare_stocks_row2').hide();
      $('compare_stocks_minimised_content').show();
      $('compare_stocks_when_minimised1').show();
      $('compare_stocks_when_maximised1').hide();
    } else {
      $('compare_stocks_row1').show();
      $('compare_stocks_row2').show();
      $('compare_stocks_minimised_content').hide();
      $('compare_stocks_when_minimised1').hide();
      $('compare_stocks_when_maximised1').show();
    }
  },
  redraw: function()
  {
//    alert('this.stock_ids: '+this.stock_ids);
    if (this.stock_ids.length == 0)
    {
      this.show(false);
    } else {
      this.show(true);
    }
    $('compare_stocks_num_stocks1').innerHTML = this.stock_ids.length;
    this.redrawMinimised();
  },
  minimise: function(maximise)
  {
    var minimise = true;
    if (arguments.length > 0)
    {
      minimise = !arguments[0];
    }
    this.is_minimised = minimise;
    this.redrawMinimised();
    
    var now = new Date();
    var that = this;
    new Ajax.Request(this.base_ajax_url,{
      method: 'GET',
      parameters: 'do='+(minimise?'minimise':'maximise')+'&timestamp='+now.getTime(),
      onSuccess: function(json_response)
      {
        json_response_object = json_response.responseText.evalJSON();
        var response = {responseText: json_response_object.responseText};
        var json = json_response_object.json;
        
        if (json.eval_before_exists)
        {
          eval(json.eval_before);
        }
        if (json.ok)
        {
          if (json.replace_stocks_list)
          {
            $('compare_stocks_list').innerHTML = response.responseText;
          }
        } else {
          if (json.alert_error)
          {
            alert(json.error);
          }
        }
        that.redraw();
        if (json.eval_after_exists)
        {
          eval(json.eval_after);
        }
      }
    });
  },
  maximise: function()
  {
    this.minimise(true)
  }
};