// This may look like C code, but it is really -*- C++ -*-
// RTSS --- Railway Total System Simulator
// (c) TAKAGI Ryo (at Prof. SONE's Laboratory, the Univ. of Tokyo.)
// rf_pfile.cc --- read data from files: P file
// $Id: rf_pfile.cc,v 2.4 1994/12/27 12:03:47 rt Exp $

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>

#include "kidenrt.hh"

#ifdef SJIS_ICONV
#include "rtss_iconv.hh"
#endif


// train class 関係のファイル読み込み
void
feeder :: rf_pfile
()
{
  if ( p_xml )
  {
    string train_type_utf8 ;
    string train_type_sjis ;

    // -----
    // Loading file.
    // ファイルロード。
    // -----
    string p_file_full_path = "" ;
    if ( is_backslash )
    {
      p_file_full_path += p_drive_str ;
    }
    p_file_full_path += p_dir_str ;
    if ( is_backslash )
    {
      p_file_full_path += "\\" ;
    }
    else
    {
      p_file_full_path += "/" ;
    }
    p_file_full_path += p_file_str ;
    TiXmlDocument p_doc ( p_file_full_path ) ;
    bool loadOkay = p_doc . LoadFile () ;
    if ( ! loadOkay )
    {
      cerr << "Failed to load file \"" << p_file_full_path << "\"." << endl ;
      exit ( 1 ) ;
    }

    // -----
    // The file must have one "root" element of tag <rtss_p_file>.
    // If multiple <rtss_p_file> tags exist, only the first one is read.
    // このXMLファイルには <rtss_p_file> というタグがなければならない。
    // <rtss_p_file> タグが複数あれば最初のだけを読む。
    // -----
    const TiXmlNode * p_doc_cd = p_doc . FirstChild () ;
    while ( p_doc_cd && p_doc_cd -> Type () != TiXmlNode :: TINYXML_ELEMENT )
    {
      p_doc_cd = p_doc_cd -> NextSibling () ;
    }
    if ( ! p_doc_cd
         || p_doc_cd -> Type () != TiXmlNode :: TINYXML_ELEMENT
         || string ( p_doc_cd -> Value () ) != "rtss_p_file" )
    {
      cerr << "Failed to find element \"rtss_p_file\"" << endl
           << " in file \"" << p_file_full_path << "\"." << endl ;
      exit ( 1 ) ;
    }

    // -----
    // Getting child element(s) of tag <rtss_p_file>. All of them must be
    // of tag <train_data_set>.
    // <rtss_p_file> の子を取得. すべて <train_data_set> タグでなければ
    // ならない。
    // -----
    for ( TiXmlNode const * p_doc_ch = p_doc_cd -> FirstChild () ;
          p_doc_ch ; p_doc_ch = p_doc_ch -> NextSibling () )
    {
      // -----
      // Ignore non-Element node.
      // エレメント以外は無視。
      // -----
      if ( p_doc_ch -> Type () != TiXmlNode :: TINYXML_ELEMENT )
      {
        continue ;
      }

      // -----
      // Check tag name.
      // タグ名チェック。
      // -----
      string pch_val = p_doc_ch -> ValueStr () ;
      if ( pch_val != "train_data_set" )
      {
        cerr << "Error: \"" << pch_val << "\" tag not allowed in P_file."
             << endl ;
        exit ( 1 ) ;
      }

      // ----
      // Get name of the train data set.
      // 列車データセットの名前を得る。
      // ----
      TiXmlAttribute const * attr
        = p_doc_ch -> ToElement () -> FirstAttribute () ;
      bool sw_class_found = false ;
      while ( attr )
      {
        if ( string ( attr -> Name () ) == "class" )
        {
          // Attribute "name"
          if ( sw_class_found )
          {
            cerr << "ERROR: Class name already defined in tag "
                 << "<train_data_set>" << endl ;
            exit ( 1 ) ;
          }
          sw_class_found = true ;
          train_type_utf8 = attr -> ValueStr () ;
#ifdef SJIS_ICONV
          // Enable this on Japanese Windows environment only
          iconv_t ixx = iconv_open ( "SHIFT_JIS" , "UTF-8" ) ;
          if ( ixx == ( iconv_t ) ( - 1 ) )
          {
            cerr << "ERROR: ICONV initialisation failed" << endl ;
            exit ( 1 ) ;
          }
          string :: size_type len = train_type_utf8 . length () ;
          char * buf_out = new char [ len + 1 ] ;
          convertFromUTF8ToSJIS ( train_type_utf8 . c_str () , buf_out , len ) ;
          train_type_sjis = string ( buf_out ) ;
          delete [] buf_out ;
#else
          train_type_sjis = train_type_utf8 ;
#endif // SJIS_ICONV
          l_ofs << "Train type name: " << train_type_sjis << endl ;
        }
        else
        {
          cerr << "ERROR: tag <train_data_set> with incorrect attribute "
               << attr -> Name () << endl ;
          exit ( 1 ) ;
        }
        attr = attr -> Next () ;
      }

      // ----
      // Get an instance of class traindata.
      // class traindata のインスタンスをひとつ得る。
      // ----
      string errstr = "Type " + train_type_utf8 + " in file "
        + p_file_full_path ;
      if ( _trd . find ( train_type_utf8 ) != _trd . end () )
      {
        cerr << "Error parsing " << errstr << ": " << endl ;
        cerr << " Duplicate type name" << endl ;
        exit ( 1 ) ;
      }
      traindata * xx = new traindata ;
      xx -> readfile_xml ( p_doc_ch , errstr ) ;
      _trd [ train_type_utf8 ] = xx ;
    }
  }
  else
  {
    FILE * pbdata = fopen ( p_file , "r" ) ;
    if ( pbdata == 0 ) err_access ( p_file ) ;
    traindata * xo = new traindata ;
    xo -> readfile ( pbdata , p_file ) ;
    fclose ( pbdata ) ;
    _trd [ p_file ] = xo ;
  }
  for ( int i = 0 ; i < ncar ; ++ i )
  {
    string train_data_key ( p_file ) ;
    if ( p_xml )
    {
      train_data_key = getCAR ( i ) . getTrainTypeKey () ;
    }
    map < string , traindata * > :: const_iterator
      ii = _trd . find ( train_data_key ) ;
    if ( ii == _trd . end () )
    {
      cerr << "Error: key " << train_data_key
           << " not found in train data search" << endl ;
      exit ( 1 ) ;
    }
    traindata const * x = ii -> second ;
    getCAR ( i ) . setcscomm ( x -> ccx ) ;
    getCAR ( i ) . setpbdata ( x -> p , x -> b , x -> a ) ;
    getCAR ( i ) . setconges ( x -> cong ) ;
    getCAR ( i ) . setAuxiliaryLoad ( x -> auxcurr , x -> sw_aux_power ) ;
    getCAR ( i ) . setShiboriFlags
      ( x -> sw_torque_shibori , x -> sw_shibori_parallel ,
        x -> sw_regenoffantei , x -> sw_anteimotor ) ;
    getCAR ( i ) . setweight ( x -> wta , x -> wtb , x -> wtc , x -> wtd ) ;
    getCAR ( i ) . setrsc ( x -> rca , x -> rcb , x -> rcc , x -> rcd ,
                            x -> rce , x -> rcf ) ;
    getCAR ( i ) . setmres ( x -> mra , x -> mrb , x -> mrc , x -> mrd ) ;
    getCAR ( i ) . setOBESS ( x -> _ess ) ;
  }
}
