package org.j69.eewiki.util;

import java.util.ArrayList;

import org.j69.eewiki.util.DiffPrint.*;

/**
 * 文字列操作系のユーティリティクラス
 *
 * @author <a href="mailto:agata@mobster.jp">Toshitaka Agata</a>
 * @author T.Yoshikai
 * @version $Revision: 1.3 $ $Date: 2003/06/30 17:07:41 $
 */

public class StringUtil {
    /** デフォルト区切り文字：カンマ */
    private static final String DEFAULT_DELIM = ",";

    // join
    //--------------------------------------------------------------------------
    /**
     * 文字列の結合（カンマ区切りで結合）
     * @param str 対象文字列の配列
     * @return 結合後の文字列
     */
    public static String join(String[] list) {

        return ( join(list, DEFAULT_DELIM) );

    }
    /**
     * 文字列の連結strをdelimで連結。
     */
    public static String join(String[] str, String delim) {
        final int length = str.length;
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < length; i++) {
            buf.append(str[i]);
            if (i != length - 1) {
                buf.append(delim);
            }
        }
        return new String(buf);
    }

    // repeat
    //--------------------------------------------------------------------------
    /**
     * strをrepeat個連結した文字列を返却
     * @param str 指定文字列
     * @param repeat 文字列の連結回数
     * @return 連結後の文字列
     */
     public static String repeat(String str, int repeat){
        StringBuffer buf = new StringBuffer();
        for(int i = 0; i < repeat; i++){
            buf.append(str);
        }
        return buf.toString();
     }
    /**
     * cをrepeat個連結した文字列を返却
     * @param c 指定文字
     * @param repeat 文字列の連結回数
     * @return 連結後の文字列
     */
     public static String repeat(char c, int repeat){
        return repeat(String.valueOf(c), repeat);
     }
    // spllit
    //--------------------------------------------------------------------------

    /**
     * 文字列の分割(カンマ区切り)
     * @param str 対象文字列
     * @return 分割後の文字列
     */
    public static String[] split(String str) {

        return ( split(str, DEFAULT_DELIM) );

    }
    /**
     * 文字列の分割（区切り文字指定）
     * @param str 対象文字列
     * @param str 区切り文字列
     * @return 分割後の文字列
     */
    public static String[] split(String str, String delim) {

        final int delimLength = delim.length();
        int pos = 0;
        int index = 0;
        ArrayList list = new ArrayList();

        while((index = str.indexOf(delim, pos)) != -1) {
            list.add(str.substring(pos, index));
            pos = index + delimLength;
        }
        list.add(str.substring(pos));

        return ( (String[])list.toArray(new String[0]) );

    }

    // replaceNull
    //--------------------------------------------------------------------------
    /**
     * nullの空文字への置換。<br>
     * 文字列がnullの場合、""（空文字）を返します。。
     * 文字列がnullでない場合、元の文字列を返します。
     * @param str 対象の文字列
     * @return 置換処理後の文字列
     */
    public static String replaceNull(String str) {
        return (replaceNull(str, ""));
    }

    /**
     * nullの指定文字列への置換。<br>
     * strがnullの場合、newStrを返します。
     * 文字列がnullでない場合、strをそのまま返します。
     * @param str 対象の文字列
     * @param rep 対象の文字列
     * @return 置換処理後の文字列
     */
    public static String replaceNull(String str, String repStr) {
        return (str == null ? replaceNull(repStr) : str);
    }

    // 部分文字列の取り出し
    //--------------------------------------------------------------------------
    /**
     * 文字列の右端から、指定文字数分の文字列を取得します。<br>
     * @param str 対象の文字列
     * @param n 文字数
     * @return 文字列の右端からn個分の文字列
     */
    public static String right(String str, int n) {
        return str.substring(str.length() - n);
    }

    /**
     * 文字列の左端から、指定文字数分の文字列を取得します。<br>
     * @param str 対象の文字列
     * @param n 文字数
     * @return 文字列の左端からn個分の文字列
     */
    public static String left(String str, int n) {
        return str.substring(0, n);
    }

    /**
     * 文字列の指定位置に、別の文字列を挿入します。<br>
     * @param str 対象の文字列
     * @param offset 挿入位置
     * @param insertStr 挿入文字列
     * @return 挿入処理後の文字列
     */
    public static String insert(String str, int offset, String insertStr) {
        StringBuffer buffer = new StringBuffer(str);
        buffer.insert(offset, insertStr);
        return buffer.toString();
    }

    // trim系
    //--------------------------------------------------------------------------
    /**
     * 文字列から前後の0を取り除きます<br>
     * @param str 対象の文字列
     * @return 処理後の文字列
     */
    public static String trimZero(String str) {
        return trim(str, '0');
    }

    /**
     * 指定文字でtrim処理をおこないます<br>
     * @param str 対象の文字列
     * @param c 指定文字
     * @return 処理後の文字列
     */
    public static String trim(String str, char c) {
        int startIndex = 0;
        while(str.charAt(startIndex) == c) {
            startIndex++;
        }

        int lastIndex = str.length() - 1;
        while(str.charAt(lastIndex) == c) {
            lastIndex--;
        }
        return str.substring(startIndex, lastIndex + 1);
    }

    /**
     * strの中の全てのoldStrを文字列newStrに置換します<br>
     * @param str 対象の文字列
     * @param oldStr 置換対象文字列
     * @param newStr 置換文字列
     * @return 処理後の文字列
     */
    public static String replace(String str, String oldStr, String newStr){
        return replace(str, oldStr, newStr, 0, str.length());
    }

    /**
     * 文字列の中の指定範囲内の文字列を置き換えを行います。
     * 元の文字列中に置き換え対象文字列がない、元の文字列長より置き換えの対象とする
     * startOffsetが大きい場合はそのまま元の文字列を返します。
     * @param str 元となる文字列
     * @param oldStr 置き換え対象文字列
     * @param newStr 置き換え後の文字列
     * @param int startOffset 置換開始位置
     * @param int endOffset 置換終了位置
     */
    public static String replace(String str, String oldStr, String newStr, int startOffset, int endOffset){
        final String subStr = str.substring(0, endOffset);
        StringBuffer buffer = new StringBuffer(str.substring(0, startOffset));
        int pos = startOffset;
        int oldPos = pos;
        while(oldPos <= endOffset && (pos = subStr.indexOf(oldStr, oldPos)) != -1){
            buffer.append(subStr.substring(oldPos, pos));
            buffer.append(newStr);
            oldPos = pos + oldStr.length();
        }
        buffer.append(str.substring(oldPos));
        return buffer.toString();
    }

    // 指定文字が存在するかどうかのチェック
    //--------------------------------------------------------------------------
    /**
     * 指定文字が存在するかどうかのチェック。<p>
     * 文字列str2のキャラクタが文字列str1に１文字でも含まれていれば
     * trueを返します。
     * @param str1 対象の文字列
     * @param str2 チェック文字
     * @return 存在すればtrue, それ以外はfalse
     */
    public static boolean containsChar(String str1, String str2) {
        for (int i = 0; i < str2.length(); i++) {
            if(str1.indexOf(str2.charAt(i)) != -1) {
                return true;
            }
        }
        return false;
    }
    /**
     * 指定文字が存在するかどうかのチェック。<p>
     * キャラクタ配列の文字が文字列str1に１文字でも含まれていれば
     * trueを返します。
     * @param str 対象の文字列
     * @param c チェック文字
     * @return 存在すればtrue, それ以外はfalse
     */
    public static boolean containsChar(String str, char[] c) {
        for (int i = 0; i < c.length; i++) {
            if(str.indexOf(c[i]) != -1) {
                return true;
            }
        }
        return false;
    }

    private static final String ALPHA =
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    /**
     * アルファベットのみで構成される文字列かどうかを判定<p>
     * @param str 対象の文字列
     * @return アルファベットのみならtrue, それ以外はfalse
     */
    public static boolean isAlpha(String str) {
        for (int i = 0; i < str.length(); i++) {
            if(ALPHA.indexOf(str.charAt(i)) == -1) {
                return false;
            }
        }
        return true;
    }
    /**
     * 文字列strが指定文字数以下ならば、後ろにスペースを付加する。
     * @param str 対象の文字列
     * @param length 文字数
     * @return 処理後の文字列。長さはlengthと一致
     */
    public static String fillChar(String str, int length, char c) {
        final int count  = length - str.length();
        if(count > 0) {
            return str + repeat(c, count);
        } else {
            return str;
        }
    }
    /**
     * 文字列strが指定文字数以下ならば、後ろにスペースを付加する。
     * @param str 対象の文字列
     * @param length 文字数
     * @return 処理後の文字列。長さはlengthと一致
     */
    public static String fillSpace(String str, int length) {
        return fillChar(str, length, ' ');
    }

    /**
     * 文字列の比較をおこなう（DiffJava使用）
     * @param oldScript
     * @param newScript
     * @param 結果表示スタイル
     * @return diffした結果文字列
     */
    public static String diff(String oldScript, String newScript, char style) {

        String[] olddata = oldScript.split("\n");
        String[] newdata = newScript.split("\n");

        Diff wikiDiff = new Diff(olddata,newdata);
        Diff.change script = wikiDiff.diff_2(false);
        if (script == null) {
            return "";
        }
        Base p = null;
        switch (style) {
        case 'e':
            p = new EdPrint(olddata, newdata);
            break;
        case 'c':
            p = new ContextPrint(olddata, newdata);
            break;
        case 'u':
            p = new UnifiedPrint(olddata, newdata);
            break;
        case 'w':
            //p = new WikiDiffPrint(olddata, newdata);
			p = new WikiDiffPrint2(olddata, newdata);
            break;
        case 'n':
            p = new NormalPrint(olddata, newdata);
        }
        return p.print_script(script);
    }
}
