#region << Using Directives >>
using System;
using System.Globalization;
#endregion
namespace Volpe.Cafe.Utils
{
    public class Interaction
    {
        #region 
        #region 
        public static void Swap(ref int x, ref int y)
        {
            if (x != y) { int tmp = x; x = y; y = tmp; }
        }
        public static void Swap(ref double x, ref double y)
        {
            if (x != y) { double tmp = x; x = y; y = tmp; }
        }
        public static void Swap(ref object x, ref object y)
        {
            if (!x.Equals(y)) { object tmp = x; x = y; y = tmp; }
        }
        #endregion
        #region 
        public static bool IsNumeric(object value)
        {
            double result;
            return double.TryParse(GetString(value), NumberStyles.Any, NumberFormatInfo.InvariantInfo, out result);
        }
        public static bool GetBool(object value)
        {
            return GetString(value).Equals("TRUE");
        }
        public static byte GetByte(object value)
        {
            return (byte)GetDouble(value, false);
        }
        public static short GetInt16(object value)
        {
            return (short)GetDouble(value, false);
        }
        public static int GetInt32(object value)
        {
            return (int)GetDouble(value, false);
        }
        public static long GetInt64(object value)
        {
            return (long)GetDouble(value, false);
        }
        public static double GetDouble(object value)
        {
            return GetDouble(value, true);
        }
        static double GetDouble(object value, bool checkNaN)
        {
            string valueStr = GetString(value);
            if (checkNaN && valueStr == "NAN") { return double.NaN; }
            double result = 0;
            double.TryParse(valueStr, NumberStyles.Any, NumberFormatInfo.InvariantInfo, out result);
            return result;
        }
        public static char GetChar(object value)
        {
            string str = GetString(value);
            return str.Equals(string.Empty) ? '\0' : str[0];
        }
        public static string GetString(object value)
        {
            return (value == null) ? string.Empty : value.ToString().Trim().ToUpper();
        }
        #endregion
        #region 
        public static Array CloneArray(Array value, Type elementType)
        {
            if (value == null) { return null; }
            else
            {
                Array destination;
                if (value.Rank == 1) { destination = Array.CreateInstance(elementType, value.Length); }
                else
                {   
                    int[] lens = new int[value.Rank];
                    for (int i = 0, lenCount = value.Rank; i < lenCount; i++)
                    {
                        lens[i] = value.GetLength(i);
                    }
                    destination = Array.CreateInstance(elementType, lens);
                }
                Array.Copy(value, destination, value.Length);
                return destination;
            }
        }
        public static Array ResizeArray(Array arr, Type type, int newLength, bool preserve)
        {
            Array newArr = Array.CreateInstance(type, newLength);
            if (preserve)
            {   
                int arrLen = arr.Length;
                if (arrLen > newLength) { arrLen = newLength; }
                Array.Copy(arr, newArr, arrLen);
            }
            return newArr;
        }
        #endregion
        #region 
        public static bool StringCompare(string value1, string value2, bool fuzzy)
        {
            if (!fuzzy)
            {   
                if (value1.Length != value2.Length) { return false; }
                if (string.Equals(value1, value2)) { return true; }
            }
            if (fuzzy) { StringPrepareFuzzy(ref value1, ref value2); }
            return (string.Compare(value1, value2, true) == 0);
        }
        public static bool StringCompareAny(string value, string[] comparands, bool fuzzy)
        {
            int index;
            return StringCompareAny(value, comparands, fuzzy, out index);
        }
        public static bool StringCompareAny(string value, string[] comparands, bool fuzzy, out int index)
        {
            index = -1;
            if (comparands == null || comparands.Length == 0) { return false; }
            for (int i = 0; i < comparands.Length; i++)
            {   
                if (StringCompare(value, comparands[i], fuzzy)) { index = i; return true; }
            }
            return false;
        }
        public static bool StringContains(string value, string substring, bool fuzzy)
        {
            if (fuzzy) { StringPrepareFuzzy(ref value, ref substring); }
            if (value.Length < substring.Length) { return false; }  
            if (string.Equals(value, substring)) { return true; }  
            value = value.ToUpper();
            substring = substring.ToUpper();
            return (value.IndexOf(substring) != -1);
        }
        public static bool StringStartsWith(string value, string substring, bool fuzzy)
        {
            if (fuzzy) { StringPrepareFuzzy(ref value, ref substring); }
            if (value.Length < substring.Length) { return false; }  
            if (string.Equals(value, substring)) { return true ; }  
            value = value.ToUpper();
            substring = substring.ToUpper();
            return value.StartsWith(substring);
        }
        static void StringPrepareFuzzy(ref string value1, ref string value2)
        {
            value1 = StringRemoveWhitespacePunctuationAndSpecialChars(value1);
            value2 = StringRemoveWhitespacePunctuationAndSpecialChars(value2);
        }
        public static string RemoveSpecialChars(string value, char c)
        {
            int spCharCount = SpecialChars.Length;
            for (int i = 0; i < spCharCount; i++)
            {
                if (value.IndexOf(SpecialChars[i]) != -1)
                {
                    value = value.Replace(SpecialChars[i], c);
                }
            }
            return value;
        }
        #endregion
        #region 
        public static string GetTitleCase(string value)
        {
            char[] chars = value.ToCharArray();
            for (int i = 0, count = value.Length; i < count; i++)
            {
                bool isTitleChar = (i == 0 || ((chars[i - 1] < 48 || chars[i - 1] > 57) &&
                    (chars[i - 1] < 65 || chars[i - 1] > 90) && (chars[i - 1] < 97 || chars[i - 1] > 122)));
                int c = chars[i];
                if (isTitleChar) { if (c >= 97 && c <= 122) { chars[i] = (char)(c - 32); } }
                else if (c >= 65 && c <= 90) { chars[i] = (char)(c + 32); }
            }
            return new string(chars);
        }
        public static string GetTitleCase(string value, int minLength)
        {
            return (value.Length >= minLength) ? GetTitleCase(value) : value;
        }
        static bool IsLetterOrNumber(char c)
        {
            return (c >= 48 && c <= 57) || (c >= 65 && c <= 90) || (c >= 97 && c <= 122);
        }
        static bool IsNotLetterOrNumber(char c)
        {
            return (c < 48 || c > 57) && (c < 65 || c > 90) && (c < 97 || c > 122);
        }
        #endregion
        #region 
        public static string GetTimeString(long value)
        {
            long sec = value / 1000;
            long s = sec % 60,
                 m = sec / 60 % 60,
                 h = sec / 3600 % 24,
                 d = sec / 86400;
            return ((d != 0) ? d.ToString() + "." : "") + h.ToString("00:") + m.ToString("00:") + s.ToString("00");
        }
        public static string GetTimeString(TimeSpan value)
        {
            return GetTimeString(value.Ticks / 10000);
        }
        #endregion
        #region 
        public static string StringRemoveWhitespacePunctuationAndSpecialChars(string value)
        {
            return StringRemove(StringRemove(value, BaseRemove), ExtRemove);
        }
        static string StringRemove(string value, string[] chars)
        {
            for (int i = 0; i < chars.Length; i++)
            {
                value = value.Replace(chars[i], "");
            }
            return value;
        }
        #endregion
        #endregion
        #region 
        public const int CY = 40;
        static readonly string[] BaseRemove = new string[] { " ", "\t", "\r", "\n", "-", "_" };
        static readonly string[] ExtRemove = new string[] {".", ",", "!", "?", "@", "#", "$", "%", "^", "&", "*", "(", ")",
            "{", "}", "[", "]", "'", "\"", "/", "\\", "|" };
        static readonly char[] SpecialChars = new char[] { '/', '\\', ':', '*', '?', '"', '<', '>', '|' };
        #endregion
    }
}

