// This may look like C code, but it is really -*- C++ -*-
// RTSS --- Railway Total System Simulator
// (c) TAKAGI Ryo (at Kogakuin University)
// stn_arrv.cc --- functions for class station_obj: train arrival control
// -----
// ChangeLog:
// 2007. 11. 22
//  Redirected log messages to l_file.
// -----

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>

#include "stnobj.hh"
#include "train.hh"
#include "StrPrintf.hh"

using std :: cerr ;
using std :: endl ;



//#define DEBUG



// 列車到着告知
void
station_obj :: from_station_generate
( const train * trptr_arg )
  const
{
  /*********************************************************************
   * g_sw_station_valid および g_sw_disttrain_ended が true でない時に *
   * 呼ぶように保証すること                                            *
   *********************************************************************/
  station_obj * stox = ( station_obj * ) this ;	// const外しの cast

  // 自分がいる to_station キューを発見させる
  int imove = stox -> which_in_to_station ( trptr_arg ) ;

  if ( imove != 0 )
  {
    cerr << "Warning: Not the first data in to_station queue removed" << endl ;
  }
  from_station temp_fs ;	// 仮変数を作る
  int temp_voie ;		// 仮変数を作る

  temp_fs . tr_ptr = data [ imove ] . tr_ptr ;
  temp_voie = temp_fs . voie = data [ imove ] . voie ;
  temp_fs . notrw = data [ imove ] . notrw ;
  temp_fs . olno = data [ imove ] . olno ;
  temp_fs . tarrive = t_sim ;	// 現在時刻を入れる！！
  temp_fs . is_pass = data [ imove ] . is_pass ;
  temp_fs . is_at_station = true ;	// とりあえずこの駅にいるのですから
  temp_fs . do_not_depart = false ;
  temp_fs . tdept = t_sim + data [ imove ] . tstop ;	// 希望発車時刻
  temp_fs . tdept_delay = 0.0 ;		// とりあえずの初期化
    
  if ( stox -> train_departure [ temp_voie ] . is_at_station )
  {
    l_ofs << StrPrintf ( "Error: Stn. No. %d: Track No. %d occupied" ,
                         stnno , temp_voie ) << endl ;
    cerr << StrPrintf ( "Error: Stn. No. %d: Track No. %d occupied" ,
                        stnno , temp_voie ) << endl ;
    l_ofs << StrPrintf
      ( "       Car Nos. %d, %d" ,
        stox -> train_departure [ temp_voie ] . tr_ptr -> car_number () ,
        temp_fs . tr_ptr -> car_number () ) << endl ;
    cerr << StrPrintf
      ( "       Car Nos. %d, %d" ,
        stox -> train_departure [ temp_voie ] . tr_ptr -> car_number () ,
        temp_fs . tr_ptr -> car_number () ) << endl ;
    exit ( 62 ) ;
  }

  // train_departure [ i ] . notrw を更新
  // notrwtab [ notrw ] も更新
  int xnotrw = 0 ;
  for ( int i = 0 ; i < nvoie ; ++ i )
  {
    if ( stox -> notrwtab [ i ] )
    {
      continue ;
    }
    if ( xnotrw < temp_fs . notrw )
    {
      ++ xnotrw ;
      continue ;
    }
    stox -> notrwtab [ i ] = true ;
    temp_fs . notrw = i ;
    break ;
  }

  // 停車時分フラクチュエーションのための機構
  stox -> stationstop_variation_func ( temp_fs , imove ) ;

  // train_departure 配列にセット
  stox -> train_departure [ temp_voie ] = temp_fs ;

  // to_station 配列からデータを撤去
  stox -> remove ( imove ) ;

  // 時隔計算！
  stox -> headway_cal () ;

  for ( int i = 0 ; i < number () ; ++ i )
  {
    // 列車に対し信号現示変化を警告
    data [ i ] . tr_ptr -> tell_signal_change () ;
  }
}



// from_station オブジェクトを受けとる
// init 時前提なので受けとるだけ
void
station_obj :: from_station_init
( const from_station fsarg )
  const
{
  station_obj * stox = ( station_obj * ) this ;	// const外しの cast
  stox -> train_departure [ fsarg . voie ] = fsarg ;
}



// to_station オブジェクトを受けとる
// const 外しをするだけ
void
station_obj :: to_station_init
( to_station fsarg )
  const
{
  station_obj * stox = ( station_obj * ) this ;	// const外しの cast
  stox -> operator+= ( fsarg ) ;
}



// 列車到着告知・Vanishing タイプのオブジェクトからのワープを扱う
void
station_obj :: from_station_warp
( from_station fsarg )
  const
{
  station_obj * stox = ( station_obj * ) this ;	// const外しの cast

  if ( stox -> train_departure [ fsarg . voie ] . is_at_station )
  {
    // 当該番線がまだ使用中
    stox -> warp_queue += fsarg ;
    return ;		// とりあえず warp_queue に取り込んでおく
  }

  // train_departure [ i ] . notrw を更新
  // notrwtab [ notrw ] も更新
  int xnotrw = 0 ;
  for ( int i = 0 ; i < nvoie ; ++ i )
  {
    if ( stox -> notrwtab [ i ] )
    {
      continue ;
    }
    if ( xnotrw < fsarg . notrw )
    {
      ++ xnotrw ;
      continue ;
    }
    stox -> notrwtab [ i ] = true ;
    fsarg . notrw = i ;
    break ;
  }

  // train_departure 配列にセット
  stox -> train_departure [ fsarg . voie ] = fsarg ;

  // 時隔計算！
  stox -> headway_cal () ;

  for ( int i = 0 ; i < number () ; ++ i )
  {
    // 列車に対し信号現示変化を警告
    data [ i ] . tr_ptr -> tell_signal_change () ;
  }
}
