/**
 * Copyright (c) 2003-2004 System Integrator Corporation.
 *                 All Rights Reserved.
 */
package jp.co.sint.tools;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;

import jp.co.sint.config.SICSVConf;
import jp.co.sint.config.SIConfig;

import org.apache.log4j.Category;

/**
 * @version $Id: SICSVRead.java,v 1.0 2003/12/18 Exp $
 * @author  Jinwang Chen
 * <br>Description:CSVファイルからデータを取り込んで、分割して、データリストを作成します。
 * <p>History</p>
 * <p>Author&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Reason</p>
 *  ============&nbsp;&nbsp;&nbsp;==========&nbsp;&nbsp;===========================<br>
 * Jinwang Chen   2003/12/18           Original
 */
public class SICSVRead {
  //ログ用のインスタンスの生成
  private static Category log=Category.getInstance(SIConfig.SILOG4J_WEBSHOP_CATEGORY_NAME);
  //CSVファイル名
  private String csvFileName="";
  //行データ
  private String nextLine="";
  private BufferedReader lReader=null;
  private int lineNo=-1;
  private int lineNo2=-1;

  /**
   * <b>SICSVRead</b>
   * コンストラクタ
   * @param なし
   * @return なし
   * @throws なし
   */
  public SICSVRead(){
  }

  /**
   * <b>SICSVRead</b>
   * コンストラクタ
   * @param lCsvFileName 取込用のCSVファイル名
   * @return なし
   * @throws なし
   */
  public SICSVRead(String lCsvFileName){
    setCsvFileName(lCsvFileName);
  }

  /**
   * <b>setCsvFileName</b>
   * CSVファイルを設定します。
   * @param lCsvFileName 設定するCSVファイル名
   * @return なし
   * @throws なし
   */
  public void setCsvFileName(String lCsvFileName){
    log.debug("setCsvFileName:lCsvFileName="+lCsvFileName);
    this.csvFileName=lCsvFileName;
    try {
      lReader=new BufferedReader(new InputStreamReader(new FileInputStream(csvFileName), SIConfig.SIENCODE_SHIFT_JIS));
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
  }

  /**
   * <b>getLineNo</b>
   * 最新データの行番号を取得します。
   * @param なし
   * @return 行号
   * @throws なし
   */
  public int getLineNo(){
    return lineNo;
  }
  public int getLineNo2(){
    return lineNo2;
  }

  /**
   * <b>hasNextLine</b>
   * データがあるかどうかを判断します。
   * @param なし
   * @return 行号
   * @throws なし
   */
  public boolean hasNextLine(){
    if (lReader==null){log.error("not set input file .");return false;}

    try {
      nextLine=lReader.readLine();
      if (nextLine!=null && lineNo==-1)lineNo=1;
      else if (nextLine!=null)lineNo++;
    } catch (IOException e) {
      e.printStackTrace();
    }
    return (nextLine!=null);
  }

  /**
   * <b>nextLine</b>
   * 行データを取得します。
   * @param なし
   * @return 行データ
   * @throws なし
   */
  public String nextLine(){
    return this.nextLine;
  }

  /**
   * <b>itemList</b>
   * データリストを取得します。
   * @param なし
   * @return データリスト
   * @throws なし
   */
  public String[] itemList()throws SIErrorException{
    return itemList(this.nextLine);
  }
  
  public String[] itemList2()throws SIErrorException{
    String lCurrVal = this.nextLine;
    while (lCurrVal.split(",").length<40 && hasNextLine()) {
      lCurrVal = lCurrVal + this.nextLine;
    }
    if (nextLine!=null && lineNo2==-1)lineNo2=1;
    else if (nextLine!=null)lineNo2++;
    
    return itemList(lCurrVal);
  }

  /**
   * <b>itemList</b>
   * 行データからデータリストを取得します。
   * @param lCurrVal 行データ
   * @return データリスト
   * @throws なし
   */
  public static String[] itemList(String lCurrVal)throws SIErrorException{
    if (SIUtil.isNull(lCurrVal)) return new String[0];
    StringBuffer lResBuf=new StringBuffer("");
    ArrayList lItems = new ArrayList();
    char[] lCurrChars = lCurrVal.toCharArray();
    int ii=0;
    int tkb=0;
    boolean app=true;

    while (ii<lCurrChars.length){
      if (tkb==0||tkb==3){//項目のデータが始めていません
        app=true;
        if (lCurrChars[ii]==' '){
          tkb=0;
        }else if (lCurrChars[ii]=='"'){//クォーテーションあった
          tkb=1;
        }else if (lCurrChars[ii]==','){//nullの項目データ
          lItems.add("");
          tkb=3;
        }else{
          lResBuf.append(lCurrChars[ii]);
          tkb=2;
        }
        ii++;
      }else if (tkb==1){//項目のデータがはじめてから
        if (lCurrChars[ii]=='"'&&((ii+1)<lCurrChars.length)&&lCurrChars[ii+1]=='"'){
          lResBuf.append('"');
          ii=ii+2;
        }else if (lCurrChars[ii]=='"'){
          tkb=0;
          app=false;
          lItems.add(lResBuf.toString());
          lResBuf=new StringBuffer("");
          ii++;
          while (ii<lCurrChars.length&&lCurrChars[ii]==' ')ii++;
          if ((ii<lCurrChars.length)&&lCurrChars[ii]==SICSVConf.SICSV_TOKEN.toCharArray()[0])ii++;
          else if ((ii<lCurrChars.length)&&lCurrChars[ii]!=','){
            throw new SIErrorException(SIErrorFactory.getErrorMsg("manager.app.data.format"));
          }
        }else{
          lResBuf.append(lCurrChars[ii]);
          ii++;
        }
      }else if (lCurrChars[ii]=='"'){//singleクォーテーション、エラー
        throw new SIErrorException(SIErrorFactory.getErrorMsg("manager.app.data.format"));
      }else if (lCurrChars[ii]==','){//次の項目データ
        lItems.add(lResBuf.toString());
        lResBuf=new StringBuffer("");
        tkb=0;
        ii++;        
      }else{//項目データ
        lResBuf.append(lCurrChars[ii]);
        ii++;
      }
    }
    if(app)lItems.add(lResBuf.toString());
    return (String[])lItems.toArray(new String[0]);
  }

  /**
   * <b>close</b>
   * ファイルのリソースをクローズします。
   * @param なし
   * @return なし
   * @throws なし
   */
  public void close(){
    if (lReader!=null){
      try {
        lReader.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
}
