###########################################
package WatchQuotes;
# Mike Schilli, 2010 (m@perlmeister.com)
###########################################
use strict;
use warnings;
use AnyEvent;
use AnyEvent::HTTP;
use YAML qw(LoadFile);

###########################################
sub new {
###########################################
  my($class, %options) = @_;

  my ($home) = glob "~";

  my $self = { 
      watcher => undef,
      data    => {},
      refdata => {},
      conf_file => 
        "$home/.pidgin-stockwatch.yml",
      conf    => {},
      %options, 
  };

  bless $self, $class;
}

###########################################
sub init {
###########################################
  my($self) = @_;

  my $yml = LoadFile( $self->{conf_file} );

  for my $e ( @$yml ) {
    if( ref $e eq "HASH") {
      my($key, $val) = %$e;
      $val =~ s/%//g;
      $self->{conf}->{ $key } = $val;
    } else {
        # 2% by default
      $self->{conf}->{ $e } = 2;
    }
  }
}

###########################################
sub watch {
###########################################
  my($self, $cb) = @_;

  $self->{watcher} = AnyEvent->timer (
    after    => 10,
    interval => 300,
    cb    => sub {
      $self->fetch( $cb );
    },
  );
}

###########################################
sub fetch {
###########################################
  my($self, $cb) = @_;

  my $url = "http://" .
   "download.finance.yahoo.com/d/" .
   "quotes.csvr?e=.csv" .
   "&f=spl1p2&s=" . 
   join('+', sort keys %{ $self->{conf} });

  http_get($url, sub {
    $self->parse_csv( $_[0] );
    $self->check( $cb );
  });
}

###########################################
sub parse_csv {
###########################################
  my($self, $csv) = @_;

  for my $line ( split /\n/, $csv ) {

    my($symbol, $prev, $last, $change) = 
      map { s/[^\w\.-]//g; $_ } 
      split /,/, $line;

    next unless defined $symbol;

    $symbol = lc $symbol;

    $self->{data}->{$symbol} = 
      [ $prev, $last, $change ];
  }
}

###########################################
sub check {
###########################################
  my($self, $cb) = @_;

  if(!scalar keys %{ $self->{refdata} }) {
    $self->{refdata} = {%{$self->{data}}};
  }

  for my $stock (keys %{ $self->{data}} ) {
    if( $self->noteworthy( $stock ) ) {
      $self->{refdata} = {
          %{$self->{data}} };

        # reset 'prev'
      for my $s ( 
          keys %{$self->{refdata}} ) {
        $self->{refdata}->{$s}->[0] =
            $self->{data}->{$s}->[1];
      }
        
      $cb->( $self->message );
      last;
    }
  }
}

###########################################
sub message {
###########################################
  my($self) = @_;

  my $msg = "\n";

  for my $stock (keys %{ $self->{data} }) {
      my($prev, $last, $change) = 
         @{ $self->{data}->{$stock} };
      $msg .= "$stock: $last $change%\n";
  }

  return $msg;
}

###########################################
sub noteworthy {
###########################################
  my($self, $stock) = @_;

  my $price_ref = 
    $self->{refdata}->{$stock}->[0];

  my $price_now = 
    $self->{data}->{$stock}->[1];
  
  my $change_percent = abs( 
      ($price_now - $price_ref))/
      $price_ref*100;
  
  return($change_percent > 
         $self->{conf}->{$stock});
}

1;
