// This may look like C code, but it is really -*- C++ -*-
// RTSS --- Railway Total System Simulator
// (c) TAKAGI Ryo (at Kogakuin University)
// tellimp.cc --- communications between cars and waysides
// -----
// ChangeLog:
// 2007. 11. 22
//  Redirected log messages to l_file.
// -----

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

#include "kidenrt.hh"
#include "StrPrintf.hh"

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


//#define DEBUG

feeder_shape shape ;		  // feeder_shape
bool nsw ;			  // feeder_shape: Circle 最初の変電所
				  // にたどり着くまで true
int ncc ;		      // 最初の変電所が startnode に現れる
                  // ブランチ番号
double imp ;             // impedance 不要だろうが一応残しておく
int node ;              // SS node No.



// 車両に隣接変電所のCl, Cc の値を教える
void
feeder :: tellimp
()
{
  for ( int i = 0 ; i < ncar ; ++ i )
    getCAR ( i ) . resetnos () ;			// nosss & e を reset

  for ( int i = 0 ; i < nss ; ++ i )			// 変電所毎に Cc, Cl
    getSUB ( i ) . cccl () ;				// を計算してセット

  for ( int j = 0 ; j < feeders ; ++ j )
    tisub ( getFLN ( j ) . fdsort () ) ; // 従来引数で与えていた

#ifdef DEBUG
  cerr << "tellimp: tisub end" << endl ;
#endif
  ti_cc () ;
#ifdef DEBUG
  cerr << "tellimp: ti_cc end" << endl ;
#endif
}



void
feeder::ti_for
( int i ,
  int j ,
  feed_y & fdx )
{
  bran_node x = fdx . getElement ( i ) ;
  int xcn , pn ;
#ifdef DEBUG
  cerr << "called brannode from fdx" << endl ;
#endif
  if ( x . startnode < nss )
  {
    if ( nsw )
    {
      // 初めての変電所を過ぎたら ncc, nsw をセットする
      ncc = i ;
      nsw = false ;
    }
    node = x . startnode ;
    imp = x . impedance ;
#ifdef DEBUG
    cerr << StrPrintf ( "startnode = %i" , node ) << endl ;
#endif
    ti_efor ( x ) ;
    return ;
  }
  xcn = x . startnode - nss ;
#ifdef DEBUG
  cerr << StrPrintf ( "before reading feedershape, xcn = %i, nfline = %i" ,
                      xcn , getCAR ( xcn ) . nfline () ) << endl ;
#endif
  shape = getFLN ( getCAR ( xcn ) . nfline () ) . feedshape () ;
#ifdef DEBUG
  cerr << StrPrintf ( "after reading feedershape, shape=%i" , shape )
        << endl ;
#endif
  if ( i == 0 && shape == Long )
  {
    getCAR ( xcn ) . setnosss () ;
#ifdef DEBUG
    cerr << "after setnosss" << endl ;
#endif
    ti_efor ( x ) ;
    return ;
  }
  if ( j >= 0 )
  {
    pn = fdx . getElement ( j ) . startnode ;
#ifdef DEBUG
    cerr << "after setting pn" << endl ;
#endif
    if ( pn >= nss )
    {
      if ( getCAR ( pn - nss ) . noss () )
      {
	getCAR ( xcn ) . setnosss () ;
#ifdef DEBUG
	cerr << "after setnosss" << endl ;
#endif
	ti_efor ( x ) ;
	return ;
      }
    }
  }
  imp += x . impedance ;
  ti_efor ( x ) ;
} 



void
feeder :: ti_efor
( bran_node & x )
{
  if ( x . endnode >= nss )
  {
#ifdef DEBUG
    cerr << StrPrintf ( "x . endnode - nss = %i" , x . endnode - nss )
         << endl ;
#endif
    getCAR ( x . endnode - nss ) . setssimps ( imp , node ) ;
  }
}



void
feeder :: ti_bak
( int i ,
  int j ,
  feed_y & fdx )
{
  bran_node x = fdx . getElement ( i ) ;
  int pn ;
  if ( x . endnode < nss )
  {
    if ( nsw )
    {
      // 初めての変電所を過ぎたら ncc, nsw をセットする
      ncc = i ;
      nsw = false ;
    }
    node = x . endnode ;
    imp = x . impedance ;
#ifdef DEBUG
    cerr << StrPrintf ( "endnode = %i" , node ) << endl ;
#endif
    ti_sbak ( x ) ;
    return ;
  }
  if ( i == fdx . branch () - 1 && shape == Long )
  {
    getCAR ( x . endnode - nss ) . setnosse () ;
    ti_sbak ( x ) ;
    return ;
  }
  if ( j < fdx . branch () )
  {
    pn = fdx . getElement ( j ) . endnode ;
    if ( pn >= nss )
    {
      if ( getCAR ( pn - nss ) . nose () )
      {
#ifdef DEBUG
	cerr << "setnosse()" << endl ;
#endif
	getCAR ( x . endnode - nss ) . setnosse () ;
#ifdef DEBUG
	cerr << "setnosse() end" << endl ;
#endif
	ti_sbak ( x ) ;
	return ;
      }
    }
  }
  imp += x . impedance ;
  ti_sbak ( x ) ;
}



void
feeder :: ti_sbak
( bran_node & x )
{
  if ( x . startnode >= nss )
  {
#ifdef DEBUG
    cerr << StrPrintf ( "x . startnode - nss = %i" , x . startnode - nss )
         << endl ;
#endif
    getCAR ( x . startnode - nss ) . setssimpe ( imp , node ) ;
  }
}




void
feeder :: tisub
( feed_y & fdx )
{
  // 前進部分
  imp = 0.0 ;
  ncc = 0 ;
  nsw = true ;				// 初期化
  for ( int i = 0 ; i < fdx . branch () ; ++ i )
    ti_for ( i , i - 1 , fdx ) ;
  if ( shape == Circle )
  {
#ifdef DEBUG
    cerr << "before Circle routine" << endl ;
#endif
    ti_for ( 0 , fdx . branch () - 1 , fdx ) ;
    for ( int i = 1 ; i < ncc ; ++ i )
      ti_for ( i , i - 1 , fdx ) ;
  }

  // 後退部分
  imp = 0.0 ;
  ncc = 0 ;
  nsw = true ;				// 初期化
#ifdef DEBUG
  cerr << "kotaibubun" << endl ;
#endif
  for ( int i = fdx . branch () - 1 ; i >= 0 ; -- i )
    ti_bak ( i , i + 1 , fdx ) ;
  if ( shape == Circle )
  {
#ifdef DEBUG
    cerr << "before Circle routine in kotaibubun" << endl ;
#endif
    ti_bak ( fdx . branch () - 1 , 0 , fdx ) ;
    for ( int i = fdx . branch () - 2 ; i > ncc ; -- i )
      ti_bak ( i , i + 1 , fdx ) ;
  }	// 必ずここに来るはずである
}



void
feeder :: ti_cc
()
{
  for ( int i = 0 ; i < ncar ; ++ i )
  {
    // 車両に渡す
    if ( getCAR ( i ) . ccommand () != Ea_cvauto0 )
    {
      // Ea_cvauto0 でない車両には通信しない
      continue ;
    }
    int sn = -1 ;
    if ( getCAR ( i ) . noss () )
      sn = getCAR ( i ) . esnum () ;
    if ( getCAR ( i ) . nose () )
      sn = getCAR ( i ) . ssnum () ;
    if ( sn != -1 )
    {
      getCAR ( i ) . setcccl ( getSUB ( sn ) . cc () , getSUB ( sn ) . cl () ) ;
      continue ;
    }
#ifdef DEBUG
    cerr << StrPrintf ( "esnum, ssnum = %i %i" , getCAR ( i ) . esnum () ,
                         getCAR ( i ) . ssnum () ) << endl ;
#endif
    double xcc = getSUB ( getCAR ( i ) . esnum () ) . cc () ;
    double xcl = getSUB ( getCAR ( i ) . esnum () ) . cl () ;
    double ycc = getSUB ( getCAR ( i ) . ssnum () ) . cc () ;
    double ycl = getSUB ( getCAR ( i ) . ssnum () ) . cl () ;
    if ( ycc < xcc ) xcc = ycc ;
    if ( ycl < xcl ) xcl = ycl ;
    getCAR ( i ) . setcccl ( xcc , xcl ) ;
  }
}
