(function($) {
  $(document).ready(function() {
    $('#articles .details h4 a').click(function(event) {
      // $(this.parent).find('.article_content').toggle();
      // $(this.parent.parent.parent).removeClass('updated_recently');
    });
    // Put in volume level
    AudioPlayer.update_volume(100);
    apply_graphics();
    if ($.fn.media) {
      $('.media').media();
    }
    // Ticker updating every few seconds
    setInterval(function() {
      // Only do if on portal page, send last ID to hint page state
      if ($('#headline h1').length) {
        $.ajax({
          dataType:'script', 
          type:'get', 
          url:'/tickers/' + window.ticker_scan_interval + '?last_item=' + $('#headline h1')[0].id})
      }
    }, window.ticker_scan_interval);
    // Digital Clock
    if ($.fn.jclock) {
      $('.digital_clock .timer').jclock({
        utc: true,
        utc_offset: window.time_zone
        });
    }
    // jQuery Navigation Effects
    if ($.fn.spriteNavigtion) {
      $('.public #navigation ul').spriteNavigtion({});
    }
    // Render Clocks
    if (window.CanvasRenderingContext2D && window.CoolClock && $('#clocks').length) {
      $(clock_offsets).each(function() {
        $('#clocks').append(
          '<div class="canvas">' + 
          '<canvas id="clock_' + this.shift() + 
          '" class="CoolClock:ransquawk:31:noSeconds:' + this.shift() +'">' + 
          '</canvas></div>');
      });
      // We need to manually init dynamically created canvases in MSIE, because it sucks
      if (window.G_vmlCanvasManager) {
        $('canvas').each(function() { G_vmlCanvasManager.initElement(this) });
      }
      // Init clocks
      $('#clocks').show();
      CoolClock.findAndCreateClocks();
    }
    // Quotes
    if ($('.quotes').length) {
      BatsFeed.update_active_trading();
      setInterval(BatsFeed.update_active_trading, 15 * 1000);
    }
    // Ticker tape
    tape = $('#quote_ticker div');
    tape.attr('scrollamount', 1);
    if ($.fn.marquee) {
      $('#quote_ticker div').marquee().
        mouseover(function () { $(this).trigger('stop');    }).
        mouseout( function () { $(this).trigger('start');   }).
        mouseup(  function () { $(this).data('drag', false);}).
        mousemove(function (event) {
          if ($(this).data('drag') == true) {
            this.scrollLeft = 
              $(this).data('scrollX') + 
              ($(this).data('x') - event.clientX);
          }}).
        mousedown(function (event) {
          $(this).
            data('drag', true).
            data('x', event.clientX).
            data('scrollX', this.scrollLeft);
        });
    }
    // Panel tool tips
    if ($.fn.qtip) {
      options = { 
        fade: 250, 
        delay: 0, 
        style: { 
          width: '128px',
          border: {
            width: 1,
            color: '#ddd' } },
        position: { 
          corner: { 
            target: 'bottomLeft',
            tooltip: 'topRight' } } }
      $('.hide_panel').qtip(options);
      $('.show_panel').qtip(options);
      $('.pop_up').qtip(options);
    }
  });

  // Apply curved corners, title shadows
  window.apply_graphics = function() {
    if ($.fn.corner) {
      $('.rounded').corner({ radius: 6 });
    }
    if ($.fn.dropShadow) {
      $(' .title h2, .title h1').dropShadow({ 
        opacity:  1.0,
        left:     2,
        top:      2,
        blur:     0 });
    }
  }
  
  // Java error
  window.show_java_install_warning = function() {
    if (window.navigator && navigator.javaEnabled && navigator.javaEnabled()) return;
    $('.no_java').remove();
    $('<p class="warning no_java"><a href="http://java.com/en/download/" ' + 
      'onclick="window.open(this.href).focus(); return false;">Click ' + 
      'here to go to the Java installation page</a>.<br />' + 
      '<small class="note">This is needed in order to listen to the audio ' + 
      'squawk.</small></p>').
      insertAfter('#main_column .title:first').
      effect('pulsate', { pulses: 2 }, 1000);
  }
  
  // Article Formatting
  window.apply_article_view = function() {
    $('.headlines tr').hover(
      function() { $(this).addClass('hovering'); },
      function() { $(this).removeClass('hovering'); }).
      find('.article_content').hide();
    $('.recently_updated').effect('pulsate');
  }

  window.hide_panel = function(container) {
    $(container).
      find('.content').hide('slow').end().
      find('.hide_panel').hide().end().
      find('.show_panel').show();
  }

  window.show_panel = function(container) {
    $(container).
      find('.content').show('slow').end().
      find('.hide_panel').show().end().
      find('.show_panel').hide();
  }

  // Refresh articles form time to time
  window.reload_articles = function() {
    if (window.article_refresh_url) {
      $.ajax({ 
        dataType: 'script', 
        type: 'get', 
        url: window.article_refresh_url }); 
      return false;
    }
  }
  
  window.utc_date = function() {
    now = new Date;
    localTime = now.getTime();
    localOffset = now.getTimezoneOffset() * 60000;
    utc = localTime + localOffset;
    return new Date(utc);
  }
  
  // Audio Player.
  window.AudioPlayer = {

    volume_scale: 100,

    // Slightly hacky player instance locator! 
    instance: function() {
      return $('.audio_player').filter( function () { 
        try {
          AudioPlayer.volume_scale = this.get_volume();
          return true;
        } catch(error) {
          return false;
        }
      }).get().pop();
    },
    
    // Create event hooks
    create_controls: function(play_button, stop_button) {
      if (! AudioPlayer.instance()) {
        show_java_install_warning();
      }
      $(play_button).
        click(function() {
          $(this).hide();
          $('#stop_button').show();
          AudioPlayer.show_volume();
          AudioPlayer.instance().play_sound();
        }).
        appendTo('#audio_player_control');
      $(stop_button).
        click(function() {
          $(this).hide();
          $('#audio_player_volume').hide();
          AudioPlayer.instance().stop();
          $('#play_button').show();
        }).
        appendTo('#audio_player_control').
        hide();
    },
    
    // Set controls depending on state of the audio player
    update_controls: function() {
      player = AudioPlayer.instance();
      if (! (player && $('#audio_player_control').length) )
        return undefined;
      if (player.is_playing()) {
        $('#stop_button').show();
        $('#play_button').hide();
        AudioPlayer.show_volume();
      } else {
        $('#stop_button').hide();
        $('#play_button').show();
      }
    },
    
    // Volume controls
    show_volume: function() {
      $('#audio_player_volume').show();
      $('.volume_up').unbind().click(function() { 
        AudioPlayer.volume_up(10);   
      });
      $('.volume_down').unbind().click( function() { 
        AudioPlayer.volume_down(10); 
      });
    },
    
    // Increase volume
    volume_up: function(amount) {
      this.set_volume(this.volume_scale + amount);
    },
    
    // Decrease volume
    volume_down: function(amount) {
      this.set_volume(this.volume_scale - amount);
    },
    
    // TODO: add save volume back to user profile
    set_volume: function(level) {
      player = AudioPlayer.instance();
      if (! player || level < 0 || level > 100)
        return false;
      if (player.set_volume(level)) {
        this.volume_scale = level;
        this.update_volume(level);
      }
    },
    
    // Update volume status
    update_volume: function(level) {
      $('#volume_level').html(level + '%');
    },
    
    // Initialize extra panel areas
    initialize_extra_panels: function() {
      listen_now = $(
        '<div class="squawk listen_now">' + 
        '<a href="#" title="Click here to listen">' + 
        '<img alt="" src="/images/design/headers/squawk.gif" />' +
        '</a></div>').
        insertBefore('.channel_player .listing').
        find('a').click(function() {
          $('#channel_player .listing').show();
          $('.listen_now, .offline').hide();
          return false;
        });
      offline = $(
        '<div class="squawk offline">' + 
        '<img alt="Squawk offline. Live between 06:30-21:30 London time" src="/images/design/headers/squawk_offline.gif" />' +
        '</div>').
        appendTo('.channel_player .content');
      $('#channel_player .listing').hide();
      setInterval(AudioPlayer.update_listen_status, 4 * 1000);
      this.update_listen_status();
    },
    
    // Update according to listening hours
    update_listen_status: function() {
      player = AudioPlayer.instance();
      if (AudioPlayer.broadcasting_period()) {
        $('.channel_player .offline').hide();
        $('#channel_player').show();
      } else {
        $('.channel_player .offline').show();
        $('#channel_player').hide();
        if (player) player.stop();
      }
    },
    
    // Criteria for broadcasting
    broadcasting_period: function() {
      now = utc_date();
      return (
        now.getHours() >= 5  && 
        now.getHours() < 22  && 
        now.getDay() > 0     && 
        now.getDay() < 6);
    }
  }
  
  // Tickers etc
  window.BatsFeed = {

    // Maps columns names in JSON
    default_field_map: function(result) {
      if (result.tradeOpen) {
        return [
          'symbol', 
          'volume', 
          'capital',
          'shares_bid', 
          'price_bid', 
          'ask_price', 
          'ask_bid', 
          'price',
          'company', 
          'segment',
          'unknown' // This is always false
          ];
      } else {
        return [ 
          'symbol', 
          'volume', 
          'capital', 
          'price', 
          'shares_bid', 
          'price_bid', 
          'ask_price', 
          'ask_bid', 
          'company', 
          'segment', 
          'day_change',
          'direction' 
          ];
      }
    },

    // Update data for a given quote, node and data-set array
    update_quote_data: function(node, field_map, data) {
      $.each(field_map, function(index, name) {
        target = node.find('.' + name);
        if (!target.length) {
          return;
        }
        text = data[index];
        switch(name) {
        case 'symbol': 
          // BATS use a odd capitalisation notation to denote the company & exchange 
          segment = data[$.inArray('segment', field_map)];
          company = data[$.inArray('company', field_map)];
          node.attr('title', company);
          text = text.replace(segment, '.' + segment.toUpperCase());
          break;
        case 'day_change':
          // Calculate day percentage moment
          current_price = BatsFeed.extract_number(data[$.inArray('price', field_map)]);
          change = BatsFeed.extract_number(text);
          text = ((change / (current_price - change)) * 100).toFixed(3) + '%';
          if (change > 0.001) {
            target.removeClass('down').addClass('up');
          }
          if (change < -0.001) {
            target.removeClass('up').addClass('down');
          }
          break;
        case 'price':
          // Compare new price to current price. Highlight accordingly
          updated   = BatsFeed.extract_number(text);
          old       = BatsFeed.extract_number(target.html());
          highlight = null;
          if (updated > old)
            highlight = '#0a0';
          if (updated < old)
            highlight = '#a00';
          if (highlight)
            target.
              animate({ color: highlight }, 500).
              animate({ color: 'white' },   3500);
          break;
        }
        target.html(text);
      });
    },

    // Insert quote content based on quotes found (bit slow)
    update_existing_quotes: function(resultset, container, field_map) {
      $.each(resultset, function(_, data) {
        symbol = data[$.inArray('symbol', field_map)];
        node = $(container + ' .' + symbol);
        BatsFeed.update_quote_data(node, field_map, data);
      });
    },

    // Insert quote content based on quotes found (bit slow)
    update_highest_volume_quotes: function(content, selector, field_map) {
      $.each($(selector), function(index, node) {
        BatsFeed.update_quote_data($(node), field_map, content[index]);
      });
    },

    // Update content based on london data
    update_london: function() {
      $.getJSON('/bats/london.json', BatsFeed.update_tickers_by_volume);
    },

    // Update content based on london data
    update_usa: function() {
      $.getJSON('/bats/usa.json', BatsFeed.update_tickers_by_volume);
    },
    
    // If between 14:30 and 22:00 
    update_active_trading: function() {
      now = utc_date();
      hour = now.getHours();
      if (now.getMonth() > 3 && now.getMonth < 11) 
        hour -= 1 // DST approx for London & USA
      if ((hour > 14 || (hour == 14 && now.getMinutes() >= 30)) && hour < 22) {
        BatsFeed.update_usa();
      } else {
        BatsFeed.update_london();
      }
    },
    
    update_tickers_by_volume: function(result) {
      field_map = BatsFeed.default_field_map(result);
      // Sort by volume
      vol_index = $.inArray('volume', field_map);
      data = result.data.sort(function(a, b) {
        return BatsFeed.extract_number(b[vol_index]) - BatsFeed.extract_number(a[vol_index]);
      });
      // Apply to each set of quotes
      $.each([ '#quote_ticker .quote', 'table.quotes tr.quote' ], function(_, selector) {
        BatsFeed.update_highest_volume_quotes(result.data, selector, field_map);
      });
    },

    // Extract numeric content from strings as string often use European notation
    extract_number: function(data) {
      return parseFloat(String(data).replace(/[^\-\d\.+]/g, ''));
    }
  };
})(jQuery);
