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

import java.util.*;
import org.apache.log4j.Category;
import jp.co.sint.config.*;
import jp.livewell.baby.util.ZenHanConverter;
import jp.livewell.baby.util.HanZenConverter;

/**
 * @version $Id: SIStringUtil.java,v 1.0 2003/07/25 Exp $
 * @author Jinwang Chen <br>
 * Description: 文字列と関連するユーティリティー
 * <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>
 * J.W.Chen 2003/07/25 Original
 */

public class SIStringUtil {
  
  // ログ用のインスタンスの生成
  private static Category log = Category.getInstance(SIConfig.SILOG4J_WEBSHOP_CATEGORY_NAME);
  
  /**
   * replace lSrcの中の text1 を text2 に置換する。
   * 
   * @param lSrc 変更前の文字列
   * @param lRel 変更前の文字列
   * @param lReled 変更後の文字列
   * @return 置換された文字列
   */
  public static String replace(String lSrc, String lRel, String lReled) {
    if (lSrc == null) return null;
    int si = 0;
    int ei = 0;
    StringBuffer rtext = new StringBuffer(lSrc.length());
    
    do {
      ei = lSrc.indexOf(lRel, si);
      if (ei >= 0) {
        rtext.append(lSrc.substring(si, ei));
        rtext.append(lReled);
        si = ei + lRel.length();
      } else {
        rtext.append(lSrc.substring(si));
      }
    } while (ei >= 0);
    return (rtext.toString());
  }
  
  /**
   * isAsciiOnly ASCIIの文字のチェック
   * 
   * @param lSrc チェックの対象の文字列
   * @return true asciiの文字 false 非ASCIIの文字
   */
  public static boolean isAsciiOnly(String lSrc) {
    for (int ii = 0; ii < lSrc.length(); ii++) {
      if (lSrc.charAt(ii) > 0x7e) { return false; }
    }
    return true;
  }
  
  /**
   * split 限界によって文字列を分割します、配列を返します。
   * 
   * @param lSrcrc 元の文字列
   * @param lDelimeter 限界文字
   * @return 配列
   * @throws なし
   */
  public static String[] split(String lSrc, String lDelimeter) {
    if (SIUtil.isNull(lSrc)) return new String[0];
    
    String lMySrc = lSrc;
    Collection lResult = new ArrayList();
    int lInx = 0;
    lInx = lMySrc.indexOf(lDelimeter);
    while (lInx != -1) {
      lResult.add(lMySrc.substring(0, lInx));
      lMySrc = lMySrc.substring(lInx + lDelimeter.length());
      lInx = lMySrc.indexOf(lDelimeter);
    }
    lResult.add(lMySrc);
    return (String[]) lResult.toArray(new String[0]);
  }
  
  /**
   * toFirstUpperCase 第一の文字だけをuppercaseへ変換します
   * 
   * @param lSrc 元の文字列
   * @return 変換後の文字列
   * @throws なし
   */
  public static String toFirstUpperCase(String lSrc) {
    if (SIUtil.isNull(lSrc)) return lSrc;
    if (lSrc.length() > 0) return lSrc.substring(0, 1).toUpperCase() + lSrc.substring(1);
    return "";
  }
  
  /**
   * toFirstLowerCase 第一の文字だけをuppercaseへ変換します
   * 
   * @param lSrc 元の文字列
   * @return 変換後の文字列
   * @throws なし
   */
  public static String toFirstLowerCase(String lSrc) {
    if (SIUtil.isNull(lSrc)) return lSrc;
    if (lSrc.length() > 0) return lSrc.substring(0, 1).toLowerCase() + lSrc.substring(1);
    return "";
  }
  
  /**
   * null2Space Null値を空文字に変換します
   * 
   * @param String
   * @return String
   * @throws なし
   */
  public static String null2Space(String lSrc) {
    if (SIUtil.isNull(lSrc)) return "";
    else return lSrc;
  }
  
  /**
   * passwordChange 入力したパスワードの文字数だけ「*」を表示します
   * 
   * @param String
   * @return String
   * @throws なし
   */
  public static String passwordChange(String string) {
    if (string == null) string = "";
    StringBuffer komeString = new StringBuffer();
    komeString.append("");
    for (int ii = 0; ii < string.length(); ii++) {
      komeString.append("*");
    }
    return komeString.toString();
  }
  
  /**
   * numberFormat ３桁ずつ","を入れる
   * 
   * @param String
   * @return String
   * @throws なし
   */
  // 7.2.0 ST0100 SIQuantityTag.javaに移行
  public static String numberFormat(String string) {
    if (string == null) string = "";
    int remainder = string.length() % 3;
    StringBuffer str = new StringBuffer();
    for (int i = 0; i < string.length(); i++) {
      str.append(string.charAt(i));
      if ((i + 1 - remainder) % 3 == 0 && i != string.length() - 1) {
        str.append(',');
      }
    }
    return str.toString();
  }
  
  /**
   * <b>parenThesis</b> 括弧()をつけてStringを返します。
   * 
   * @param lString
   * @return 括弧つきlString
   */
  public static String parenThesis(String lString) {
    if (SIUtil.isNull(lString) || lString.equals("")) return "";
    return "(" + lString + ")";
  }
  
  /**
   * <b>rightTrim</b> 文字列右側の半角・全角スペースを取り除きます。
   * 
   * @param lString
   * @return
   */
  public static String rightTrim(String lString) {
    String strData = "";
    int intcnt = 0;
    
    for (int i = lString.length(); i > 0; i--) {
      // 後ろから探して最初に出現する全角空白以外の文字の出現位置を特定する
      strData = lString.substring(i - 1, i);
      if (!strData.equals("　") && !strData.equals(" ")) {
        intcnt = i;
        break;
      }
    }
    return lString.substring(0, intcnt);
  }
  
  /**
   * limitLength 表示文字数制限がある場合に、制限文字数分文字列＋省略記号 を返します。
   * 
   * @param lString 文字列
   * @param limit 表示可能文字数
   * @param end 省略記号
   * @return String
   * @throws なし
   */
  public static String limitLength(String lString, int limit, String end) {
    if (SIUtil.isNull(lString)) return "";
    if (limit == 0) return end;
    int length = lString.length();
    
    // 制限文字数以下の場合はそのままリターン
    if (length <= limit) return lString;
    char content[] = new char[length];
    lString.getChars(0, lString.length(), content, 0);
    StringBuffer result = new StringBuffer(content.length);
    for (int i = 0; i < limit; i++) {
      result.append(content[i]);
    }
    return result.toString() + end;
  }
  
  /**
   * limitLength 表示文字数制限がある場合に、<br>
   * タグを除いた制限文字数分文字列＋省略記号 を返します。
   * 
   * @param lString 文字列
   * @param limit 表示可能文字数
   * @param end 省略記号
   * @return String
   * @throws なし
   */
  public static String limitLengthExcptTags(String lString, int limit, String end) {
    StringBuffer result = new StringBuffer();
    // 7.1.1o ST0214 修正 ここから
    // StringTokenizer st = new StringTokenizer( lString,"<BR>" );
    String[] tokens = split(lString, "<BR>");
    // 7.1.1o ST0214 修正 ここまで
    int cnt = 0;
    
    boolean tagMode = false;
    StringBuffer resultTmp = new StringBuffer();
    int cntTmp = 0;
    
    label:
    // 7.1.1o ST0214 修正 ここから
    // while ( st.hasMoreTokens() ) {
    // String token = st.nextToken();
    for (int idx = 0; idx < tokens.length; idx++) {
      String token = tokens[idx];
      // 7.1.1o ST0214 修正 ここまで
      
      char content[] = new char[token.length()];
      token.getChars(0, token.length(), content, 0);
      for (int i = 0; i < token.length(); i++) {
        
        // "<"を検出したらタグモード開始
        if (!tagMode&&"<".equals(String.valueOf(content[i]))) {
          tagMode = true;
        // タグモード中に"<"を検出したら退避文字列を加算する
        }else if ("<".equals(String.valueOf(content[i]))){
          result.append(resultTmp);
          cnt = cnt + cntTmp;
          tagMode = false;
          resultTmp = new StringBuffer();
          cntTmp = 0;
          if (cnt == limit) break label;
          tagMode = true;
        }
        
        // ">"を検出したらタグモード終了して退避文字列を破棄する
        if (tagMode&&">".equals(String.valueOf(content[i]))){
          tagMode = false;
          resultTmp = new StringBuffer();
          cntTmp = 0;
        }else{
          // タグモードの場合、文字列を退避する
          if (tagMode) {
            resultTmp.append(content[i]);
            cntTmp++;
          }else{
            result.append(content[i]);
            cnt++;
          }
          if (cnt == limit) break label;
        }
      }
      result.append("<BR>");
    }
    
    // タグモードのまま終わった場合、退避文字列を加える
    if(tagMode){
      result.append(resultTmp);
      cnt = cnt + cntTmp;
      tagMode = false;
    }
    
    // 長さが短いものは省略記号はつけない
    if (cnt < limit) end = "";
    
    return result.toString() + end;
  }
  
  public static boolean isBelong(String[] strList, String str) {
    if (strList == null || strList.length < 1) return false;
    for (int i = 0; i < strList.length; i++) {
      if (str.equals(strList[i])) return true;
    }
    return false;
  }
  
  public static String toHankakuKana(String val){
    ZenHanConverter lConverter = new ZenHanConverter();
    return lConverter.convert(val).replaceAll("ー","ｰ");
  }
  
  public static String toZenkakuKana(String val){
    HanZenConverter lConverter = new HanZenConverter();
    return lConverter.convert(val).replaceAll("ｰ","ー");
  }
  
  public static String getLimitString(String data,int limit) {
    if (data.getBytes().length<=limit) return data;
    else {
      int count = 1;
      while (data.substring(0, count).getBytes().length<=limit) count++;
      return data.substring(0, count-1);
    }
  }
  
  public static String getLimitOverString(String data,int limit) {
    if (data.getBytes().length<=limit) return "";
    else {
      int count = 1;
      while (data.substring(0, count).getBytes().length<=limit) count++;
      return data.substring(count-1);
    }
  }
  
  public static String toHalf(String S){
    StringBuffer SB=new StringBuffer();
    for(int i=0;i<S.length();i++){
      SB.append(Half((int)S.charAt(i)));
    }
    return(SB.toString());
  }
  public static String toFull(String S){
    StringBuffer SB=new StringBuffer();
    for(int i=0;i<S.length();i++){
      SB.append(Full((int)S.charAt(i)));
    }
    return(SB.toString());
  }
  private static char Half(int c){
    if((c>=65296&&c<=65305)||(c>=65345&&c<=65370)){
      c-=65248;
    }
    return (char)c;
  }
  private static char Full(int c){
    if((c>=48&&c<=57)||(c>=97&&c<=122)){
      c+=65248;
    }
    return (char)c;
  }
}