// == LICENSE INFORMATION ==
/*
 * First author tiritomato 2013.
 * This program is distributed under the GNU Lesser General Public License(LGPL ver3).
 * support blog (Japanese only) http://d.hatena.ne.jp/tiri_tomato/
 */
// == LICENSE INFORMATION ==

namespace DotNetEx.String
{
    //! @addtogroup DotNetEx-String名前空間
    //! @{

    //! @brief 各種の静的な拡張メソッドや、文字列操作に関する一般的な処理を提供します。
    public static class Extention
    {
        // public implements //

        //!	@brief 例外データを文字列に変換します。InnerExceptionの入れ子構造をインデント整形で表現しています。
        public static System.String ToNestedMultilineString(this System.Exception ex) { return ToNestedMultilineString(ex, "\t"); }

		//!	@brief 例外データを文字列に変換します。InnerExceptionの入れ子構造をインデント整形で表現しています。
        public static System.String ToNestedMultilineString(this System.Exception ex, System.String indentUnit) { return ToNestedMultilineString(ex, indentUnit, 0); }

        //!	@brief 例外データを文字列に変換します。InnerExceptionの入れ子構造をインデント整形で表現しています。
        public static System.String ToNestedMultilineString(this System.Exception ex, System.String indentUnit, int indentDepth)
        {
		    IndentBuilder ret = new String.IndentBuilder(indentUnit);
		    RecursiveExceptionPrint(ret,ex,System.Math.Max(0,indentDepth));
		    return ret.ToString();
        }

        //!	@brief 文字列を繰り返す文字列を生成する
        //!	@param [in] src 繰り返す文字列
        //!	@param [in] ct 繰り返す回数
        //!	@return srcがnullptrまたはctがマイナスの時null。ctがゼロの時System::String::Empty。それ以外であれば繰り返した文字列。
        public static System.String Repeat(this System.String src, int ct)
        {
		    if ( ct == 0 ) return System.String.Empty;
		    if ( (src == null) || (ct<0) ) return null;
		    System.Text.StringBuilder sb = new System.Text.StringBuilder(src.Length * ct);
		    for ( int i = 0; i < ct; i++ ) sb.Append( src );
		    return sb.ToString();
	    }

        //! @brief 文字列同士の共通部分（積集合）を先頭から検索して取得する
        //! @details 先頭からStringComparisonで1文字ずつ比較し、一致する範囲までの長さをstr1からコピーします。
        public static System.String Intersect(this System.String str1, System.String str2, System.StringComparison opt)
        {
            if (str1 == null) str1 = System.String.Empty;
            if (str2 == null) str2 = System.String.Empty;
            int length = System.Math.Min(str1.Length, str2.Length);
            for (int index = 0; index < length; index++)
            {
                if (System.String.Equals(str1.Substring(index,1), str2.Substring(index,1), opt) == false)
                {
                    if (index == 0) return System.String.Empty;
                    return str1.Substring(0, index);
                }
            }
            return System.String.Empty;
        }

        // private implements //
	    
        private static void RecursiveExceptionPrintElement(String.IndentBuilder src, System.String name, System.String value, int indentDepth ) {
		    if ( value == null ) value = "Nothing";
		    src.AppendLine( System.String.Format("{0}:{1}{2}", name,
			    value.Contains(System.Environment.NewLine) ? System.Environment.NewLine : System.String.Empty, value ), indentDepth );
	    }

	    private static void RecursiveExceptionPrint( String.IndentBuilder src, System.Exception ex, int indentDepth ) {
		    if ( (src==null) || (ex==null) ) return;
		    System.Type t = ex.GetType();
		    RecursiveExceptionPrintElement(src, "TypeName", t.Name, indentDepth);
		    RecursiveExceptionPrintElement(src, "TypeFullName", t.FullName, indentDepth);
		    RecursiveExceptionPrintElement(src, "Message", ex.Message, indentDepth);
		    if ( ex.InnerException == null ) 
			    src.AppendLine("InnerException:Nothing", indentDepth);
		    else {
			    src.AppendLine("InnerException:", indentDepth);
			    RecursiveExceptionPrint(src,ex.InnerException,indentDepth+1);
		    }
		    RecursiveExceptionPrintElement(src,"Source", ex.Source, indentDepth);
		    RecursiveExceptionPrintElement(src,"StackTrace", ex.StackTrace, indentDepth);
	    }
    }
    //! @}
}
