{% extends "base.html" %}

{% block scripts %}
<script src='/static/js/libs/jquery.flot.js'></script>
<script type='text/javascript' src='/static/js/libs/jquery.flot.time.js'></script>
<script type='text/javascript' src='/static/js/exchange_colours.js'></script>

<script type='text/javascript'>

var default_high = {{ args['high'].amount }};
var default_low = {{ args['low'].amount }};
var current_x_max = default_high;
var current_x_min = default_low;

var show_orders = {% raw json_encode(args['show_orders']) %}
var gds_active = {% raw json_encode(args['gds_active']) %}

var poll_time = -1;

var timeout_id = undefined;

var data = {
  {% for exchange_name, levels in sorted(args['levels_for_exchange'].items(), key=lambda pair: pair[0]) %}
  '{{ exchange_name }}': {
    data: {% raw json_encode(levels) %},
    label: '{{ exchange_name.capitalize() }}',
    color: exchange_colours['{{ exchange_name.lower() }}'],
  },
  {% end %}
}

var open_orders_data = {
  {% for exchange_name, open_orders in args['open_orders_for_exchange'].items() %}
  '{{ exchange_name }}': {
    data: {% raw json_encode(open_orders) %},
    label: '{{ exchange_name.capitalize() }} Orders',
    color: exchange_colours['{{ exchange_name.lower() }}'],
    yaxis: 2,
    bars: {
      show: true,
      barWidth: 0.01,
    },
    lines: {
      show: false,
    }
  },
  {% end %}
}

plot_options = {
  series: {
    lines: {
      show: true,
      fill: true,
      steps: true,
    },
  },
  yaxes: [{
    //tickLength: 0
  }, {
    position: 'right',
    //tickLength: 0,
  }, {
    max: 1,
    show: false,
  }],
  legend: {show: true},
  xaxis: {
    min: current_x_min,
    max: current_x_max,
    //tickLength:0
  },
}

recalculate_update_y_max = function() {
  new_y_max = calculate_y_max();
  set_graph_y_max(new_y_max);
}

calculate_y_max = function() {
  max_liquidity = 0;

  for (exchange_name in data) {
    var i = 0;

    for (i; i < data[exchange_name].data.length; i++) {
      level = data[exchange_name].data[i]

      if (level[0] >= current_x_min && level[0] < current_x_max) {
        if (level[1] > max_liquidity) {
          max_liquidity = level[1]
        }
      } else if (level[0] >= current_x_max) {
        break;
      }
    }
  }

  return max_liquidity * 1.1;
}

set_graph_y_max = function(value) {
  plot_options.yaxes[0].max = value;
}

set_graph_x_max = function(value) {
  current_x_max = value;
  plot_options.xaxis.max = current_x_max;
}

set_graph_x_min = function(value) {
  current_x_min = value;
  plot_options.xaxis.min = current_x_min;
}

draw_graph_with_series = function(series) {
  var plot_data = Array();

  for (var i=0; i < series.length; i++) {
    plot_data.push(data[series[i]]);
  }

  if (show_orders == true) {
    for (var i=0; i < series.length; i++) {
      if (open_orders_data[series[i]] != undefined) {
        plot_data.push(open_orders_data[series[i]]);
      }
    }
  }

  $.plot("#levels-graph", plot_data, plot_options);
}

redraw_graph = function() {
  recalculate_update_y_max();

  var series_to_graph = Array();

  $('#series-buttons button.btn-primary').each(function() {
    series_to_graph.push($(this).attr('data-series-name'));
  });

  draw_graph_with_series(series_to_graph);
}

data_poll_start = function() {
  // Poll the json endpoint of the orderbooks handler and set data_poll_finish as the
  // completion handler.
  url = window.location + '&json=true'

  if (window.location.search == '') {
    url = window.location + '?json=true'
  }

  $.get(url, data_poll_finish);
}

create_new_orders_entry = function(exchange_name, orders_data) {
  capitalized_name = exchange_name.charAt(0).toUpperCase() + exchange_name.slice(1);
  lower_case_name = exchange_name.toLowerCase();

  new_entry = {
    data: orders_data,
    label: capitalized_name + ' Orders',
    color: exchange_colours[lower_case_name],
    yaxis: 2,
    bars: {
      show: true,
      barWidth: 0.01,
    },
    lines: {
      show: false,
    }
  }

  return new_entry;
}

data_poll_finish = function(new_data) {
  new_data = JSON.parse(new_data);

  for (exchange_name in new_data['levels']) {
    data[exchange_name].data = new_data['levels'][exchange_name]
  }

  // Remove any exchanges that no longer have open orders.
  for (exchange_name in open_orders_data) {
    if (!Object.keys(new_data['orders']).includes(exchange_name)) {
      delete open_orders_data[exchange_name];
    }
  }

  // Update entries for exchanges that already had open orders, or create a new
  // entry in the open_orders_data dict if this is a newly active exchange.
  for (exchange_name in new_data['orders']) {
    if (Object.keys(open_orders_data).includes(exchange_name)) {
      open_orders_data[exchange_name].data = new_data['orders'][exchange_name];
    } else {
      new_entry = create_new_orders_entry(
        exchange_name,
        new_data['orders'][exchange_name],
      );

      open_orders_data[exchange_name] = new_entry;
    }
  }

  redraw_graph();

  if (poll_time != -1) {
    timeout_id = setTimeout(data_poll_start, poll_time);
  } else {
    // Not continuing.
  }
}

$(document).ready(function() {
  if (gds_active == true) {
    redraw_graph();
  }

  $('#series-buttons button').click(function() {
    if ($(this).hasClass('btn-primary')) {
      $(this).removeClass('btn-primary');
      $(this).addClass('btn-light');
    } else {
      $(this).addClass('btn-primary');
      $(this).removeClass('btn-light');
    }

    redraw_graph();
  });

  $('#open-orders-button').click(function() {
    if ($(this).hasClass('btn-primary')) {
      $(this).removeClass('btn-primary');
      $(this).addClass('btn-light');
    } else {
      $(this).addClass('btn-primary');
      $(this).removeClass('btn-light');
    }

    show_orders = !show_orders;
    redraw_graph();
  });

  $('#poll-buttons button').each(function() {
    $(this).click(function() {
      $('#poll-buttons button.btn-primary').addClass('btn-light');
      $('#poll-buttons button.btn-primary').removeClass('btn-primary');

      $(this).removeClass('btn-light');
      $(this).addClass('btn-primary');

      old_poll_time = poll_time;
      new_poll_time = parseInt($(this).attr('data-poll-time'));

      if (new_poll_time == -1) {
        poll_time = -1;
        clearTimeout(timeout_id);
        timeout_id = undefined;
      } else {
        poll_time = parseInt(new_poll_time) * 1000;

        if (old_poll_time != -1) {
          clearTimeout(timeout_id);
          timeout_id = undefined;
        }

        data_poll_start();
      }
    });
  });

  $('#set-limits').click(function() {
    new_x_max = parseFloat($('#high').val());
    new_x_min = parseFloat($('#low').val());

    if (!isNaN(new_x_max)) {
      set_graph_x_max(new_x_max);
    }

    if (!isNaN(new_x_min)) {
      set_graph_x_min(new_x_min);
    }

    new_ymax = calculate_y_max();
    set_graph_y_max(new_y_max);

    redraw_graph();

    $('#high').val(current_x_max);
    $('#low').val(current_x_min);
  });
});

</script>
{% end %}

{% block css %}
<style type='text/css'>

html, body {
  height: 100%;
}

div#gds-error {
  margin-top: 250px;
}

div#levels-graph.inactive {
  border: 1px solid #000;
  background: #f6f6f6;
}

div.form-inline label {
  font-weight: normal;
  margin-right: 20px;
  padding-top: 7px;
  padding-right: 6px;
  color: #888;
  font-size: 14px;
}

input#high, input#low {
  width: 88px;
}

#graph-controls {
  padding-top: 15px;
}

div#controls-right div.row,
div#controls-left div.row {
  margin-bottom: 5px;
}

div#graph-controls {
  height: 18%;
}

</style>
{% end %}

{% block title %}
  <title>Orderbook Viewer</title>
{% end %}

{% block page_title %}
  <h1>{{ args['pair_name'] }} Orderbooks</h1>
  {% if args['at_time'] is not None %}
    <h5>at {{ args['at_time'] }}</h5>
  {% end %}
{% end %}

{% block content %}
<div class='row' id='title-row'>
  <div class='col'>
    <h4 class='align-middle'>{{ args['pair_name'] }} Orderbooks</h4>
  </div>
</div>
<div class='row h-75'>
  <div class='col d-flex flex-column'>
    {% if args['gds_active'] is False %}
      <div id='levels-graph' class='inactive'>
        <div id='gds-error' class='row'>
          <div class='col-md-5 col-md-offset-4'>
            <h4>Gryphon couldn't find a connection to GDS.</h3>
            <p>
              This dashboard requires a connection to an active GDS databse.<br/>
              <a href='https://gryphon-framework.readthedocs.io/en/latest/'>Read the docs</a> to learn how to set up and connect the gryphon data service.</p>
          </div>
        </div>
    {% else %}
      <div class='flex-grow-1' id='levels-graph'></div>
    {% end %}
  </div>
</div>
<div class='row justify-content-around' id='graph-controls'>
  <div class='col-6' id='controls-left'>
    <div class='row'>
      <div class='col'>
        <div id='series-buttons' class='btn-group'>
          {% for exchange_name in args['levels_for_exchange'].keys() %}
          <button
            id='{{ exchange_name }}-button'
            data-series-name='{{ exchange_name }}'
            {% if len(args['selected_exchanges']) == 0 or exchange_name in args['selected_exchanges'] %}
              class='btn btn-primary'
            {% else %}
              class='btn btn-light'
            {% end %}
          >{{ exchange_name }}</button>
          {% end %}
        </div>
      </div>
    </div>
    <div class='row'>
      <div class='col'>
        <div id='options-buttons' class='btn-group'>
          {% if args['gds_active'] == True %}
            <button id='open-orders-button' data-series-name='open-orders'
              {% if args['show_orders'] %}
                class='btn btn-primary'
              {% else %}
                class='btn btn-dark'
              {% end %}
            >Open Orders</button>
          {% end %}
        </div>
      </div>
    </div>
  </div>
  <div class='col-3' id='controls-right'>
    <div class='row'>
      <div class='form-inline'>
        <div class='form-group'>
          <label for='poll-buttons'>Polling</label>
          <div id='poll-buttons' class='btn-group'>
            <button id='poll-off' data-poll-time=-1 class='btn btn-primary'>Off</button>
            <button id='poll-5m' data-poll-time=300 class='btn btn-dark'>5m</button>
            <button id='poll-1m' data-poll-time=60 class='btn btn-dark'>1m</button>
            <button id='poll-30s' data-poll-time=30 class='btn btn-dark'>30s</button>
            <button id='poll-10s' data-poll-time=10 class='btn btn-dark'>10s</button>
            <button id='poll-2s' data-poll-time=2 class='btn btn-dark'>2s</button>
          </div>
        </div>
      </div>
    </div>
    <div class='row'>
      <div class='form-inline'>
        <div class='form-group'>
          <label for='high'>Graph Limits</label>
          <input id='low' type='text' class='form-control' placeholder='Low'>
          <input id='high' type='text' class='form-control' placeholder='High'>
          <button id='set-limits' class='btn btn-dark'>Set</button>
        </div>
      </form>
    </div>
  </div>
</div>
{% end %}
