require 'integration_helper'

describe "Request Contract Info", :connected => true, :integration => true do

  before(:all) do
    verify_account
    @ib = IB::Connection.new OPTS[:connection].merge(:logger => mock_logger)
    @ib.wait_for :NextValidId
  end

  after(:all) { close_connection }

  context "Request Stock data" do

    before(:all) do
      @contract = IB::Contract.new :symbol => 'AAPL', :sec_type => :stock
      @ib.send_message :RequestContractData, :id => 111, :contract => @contract
      @ib.wait_for :ContractDataEnd, 3 # sec
      # java: 15:33:16:159 <- 9-6-111-0-AAPL-STK--0.0---     ---0-- -
      # ruby: 15:36:15:736 <- 9-6-111-0-AAPL-STK--0.0---SMART--- --0-
    end

    after(:all) { clean_connection } # Clear logs and message collector

    it { @ib.received[:ContractData].should have_exactly(2).contract_data }
    it { @ib.received[:ContractDataEnd].should have_exactly(1).contract_data_end }

    it 'receives Contract Data for requested contract' do
      msg = @ib.received[:ContractData].first
      msg.request_id.should == 111
      msg.contract.should == @contract
    end

    it 'receives Contract Data with extended fields' do
      # Returns 2 contracts, one for NASDAQ and one for IBIS - internal crossing?

      @ib.received[:ContractData].each do |msg|
        contract = msg.contract
        detail = msg.contract_detail

        contract.symbol.should == 'AAPL'
        contract.local_symbol.should =~ /AAPL|APC/
        contract.con_id.should be_an Integer
        contract.expiry.should == ''
        contract.exchange.should == 'SMART'

        detail.market_name.should =~ /NMS|USSTARS/
        detail.trading_class.should =~ /NMS|USSTARS/
        detail.long_name.should == 'APPLE INC'
        detail.industry.should == 'Technology'
        detail.category.should == 'Computers'
        detail.subcategory.should == 'Computers'
        detail.trading_hours.should =~ /\d{8}:\d{4}-\d{4}/
        detail.liquid_hours.should =~ /\d{8}:\d{4}-\d{4}/
        detail.valid_exchanges.should =~ /ISLAND|IBIS/
        detail.order_types.should be_a String
        detail.price_magnifier.should == 1
        detail.min_tick.should be <= 0.01
      end
    end
  end # Stock

  context "Request Option contract data" do

    before(:all) do
      @contract = IB::Option.new :symbol => "AAPL", :expiry => "201301",
                                 :right => :call, :strike => 500
      @ib.send_message :RequestContractData, :id => 123, :contract => @contract
      @ib.wait_for :ContractDataEnd, 5 # sec
    end

    after(:all) { clean_connection } # Clear logs and message collector

    subject { @ib.received[:ContractData].first }

    it { @ib.received[:ContractData].should have_exactly(1).contract_data }
    it { @ib.received[:ContractDataEnd].should have_exactly(1).contract_data_end }

    it 'receives Contract Data for requested contract' do
      subject.request_id.should == 123
      subject.contract.should == @contract
    end

    it 'receives Contract Data with extended fields' do
      contract = subject.contract
      detail = subject.contract_detail

      contract.symbol.should == 'AAPL'
      contract.local_symbol.should == 'AAPL  130119C00500000'
      contract.expiry.should == '20130118'
      contract.exchange.should == 'SMART'
      contract.con_id.should be_an Integer

      detail.market_name.should == 'AAPL'
      detail.trading_class.should == 'AAPL'
      detail.long_name.should == 'APPLE INC'
      detail.industry.should == 'Technology'
      detail.category.should == 'Computers'
      detail.subcategory.should == 'Computers'
      detail.trading_hours.should =~ /\d{8}:\d{4}-\d{4}/
      detail.liquid_hours.should =~ /\d{8}:\d{4}-\d{4}/
      detail.valid_exchanges.should =~ /CBOE/
      detail.order_types.should be_a String
      detail.price_magnifier.should == 1
      detail.min_tick.should == 0.01
    end
  end # Request Option data

  context "Request Forex contract data" do

    before(:all) do
      @contract = IB::Contract.new :symbol => 'EUR', # EURUSD pair
                                   :currency => "USD",
                                   :exchange => "IDEALPRO",
                                   :sec_type => :forex
      @ib.send_message :RequestContractData, :id => 135, :contract => @contract
      @ib.wait_for :ContractDataEnd, 3 # sec
    end

    after(:all) { clean_connection } # Clear logs and message collector

    subject { @ib.received[:ContractData].first }

    it { @ib.received[:ContractData].should have_exactly(1).contract_data }
    it { @ib.received[:ContractDataEnd].should have_exactly(1).contract_data_end }

    it 'receives Contract Data for requested contract' do
      subject.request_id.should == 135
      subject.contract.should == @contract
    end

    it 'receives Contract Data with extended fields' do
      contract = subject.contract
      detail = subject.contract_detail

      contract.symbol.should == 'EUR'
      contract.local_symbol.should == 'EUR.USD'
      contract.expiry.should == ''
      contract.exchange.should == 'IDEALPRO'
      contract.con_id.should be_an Integer

      detail.market_name.should == 'EUR.USD'
      detail.trading_class.should == 'EUR.USD'
      detail.long_name.should == 'European Monetary Union euro'
      detail.industry.should == ''
      detail.category.should == ''
      detail.subcategory.should == ''
      detail.trading_hours.should =~ /\d{8}:\d{4}-\d{4}/
      detail.liquid_hours.should =~ /\d{8}:\d{4}-\d{4}/
      detail.valid_exchanges.should =~ /IDEALPRO/
      detail.order_types.should be_a String
      detail.price_magnifier.should == 1
      detail.min_tick.should be <= 0.0001
    end
  end # Request Forex data

  context "Request Futures contract data" do

    before(:all) do
      @contract = IB::Symbols::Futures[:ym] # Mini Dow Jones Industrial
      @ib.send_message :RequestContractData, :id => 147, :contract => @contract
      @ib.wait_for :ContractDataEnd, 3 # sec
    end

    after(:all) { clean_connection } # Clear logs and message collector

    subject { @ib.received[:ContractData].first }

    it { @ib.received[:ContractData].should have_exactly(1).contract_data }
    it { @ib.received[:ContractDataEnd].should have_exactly(1).contract_data_end }

    it 'receives Contract Data for requested contract' do
      subject.request_id.should == 147
      subject.contract.should == @contract
    end

    it 'receives Contract Data with extended fields' do
      contract = subject.contract
      detail = subject.contract_detail

      contract.symbol.should == 'YM'
      contract.local_symbol.should =~ /YM/
      contract.expiry.should =~ Regexp.new(IB::Symbols.next_expiry)
      contract.exchange.should == 'ECBOT'
      contract.con_id.should be_an Integer

      detail.market_name.should == 'YM'
      detail.trading_class.should == 'YM'
      detail.long_name.should == 'Mini Sized Dow Jones Industrial Average $5'
      detail.industry.should == ''
      detail.category.should == ''
      detail.subcategory.should == ''
      detail.trading_hours.should =~ /\d{8}:\d{4}-\d{4}/
      detail.liquid_hours.should =~ /\d{8}:\d{4}-\d{4}/
      detail.valid_exchanges.should =~ /ECBOT/
      detail.order_types.should be_a String
      detail.price_magnifier.should == 1
      detail.min_tick.should == 1
    end
  end # Request Forex data
end # Contract Data