using System.Text;
using System.IO.Compression;
using System.Globalization;
using System.Diagnostics;
using MarketData.MarketDataModel;
using System.Security.Principal;
using ThreadState=System.Threading.ThreadState;

namespace MarketData.Utils
{
  public class Utility
  {
    private static DateTime epoch = DateTime.Parse("01-01-0001");
    private static TimeSpan oneDay=new TimeSpan(1,0,0,0);


		public static String ThreadStateToString(Thread thread)
		{
		  switch(thread.ThreadState)
			{
				case ThreadState.Running :
				  return "Running";
				case ThreadState.StopRequested :
				  return "StopRequested";
				case ThreadState.SuspendRequested :
				  return "SuspendRequested";
				case ThreadState.Background :
				  return "Background";
				case ThreadState.Unstarted : 
				  return "Unstarted";
				case ThreadState.Stopped :
				  return "Stopped";
				case ThreadState.WaitSleepJoin :
				  return "WaitSleepJoin";
				case ThreadState.Suspended :
				  return "Suspended";
				case  ThreadState.AbortRequested :
				  return "AbortRequested";
				case ThreadState.Aborted :
				  return "Aborted";
				default :
				  return "Unknown";
			}
		}
    /// <summary>
    /// poses a question to the console and receives a confirmation response
    /// </summary>
    /// <param name="message">The message to ask the user.</param>
    public static bool GetVerificationToProceed(String message)
    {
        Console.Write(String.Format("{0} Y/N? ",message));
        String answer = Console.ReadLine();
        answer=answer.ToUpper();
        if(!"Y".Equals(answer))return false;
        return true;
    }

    public static long DateToUnixDate(DateTime dateTime)
    {
      DateTime javascriptEpoch=DateTime.Parse("01-01-1970 00:00:00");
      DateTime eod=new DateTime(dateTime.Year,dateTime.Month,dateTime.Day,23,0,0);      // request end of day
      TimeSpan ts=eod-javascriptEpoch;
      long longDate=(long)ts.TotalSeconds;  
      return longDate;
    }
    public static DateTime UnixDateToDate(long yahooDate)
    {
      DateTime javascriptEpoch=DateTime.Parse("01-01-1970 00:00:00");
      TimeSpan timespan=TimeSpan.FromSeconds((double)yahooDate);
      DateTime date=javascriptEpoch+timespan;
      return date;
    }

// This is being called before any trace listeners have been added
    public static bool EnsureLogFolder(String strLogFolder)
    {
      if(Directory.Exists(strLogFolder))return true;
      try
      {
        Directory.CreateDirectory(strLogFolder);
        return true;
      }
      catch(Exception)
      {
        return false;
      }
    }

    public static void ExpireLogs(String pathLogFiles,int expiryDays)
    {
      DateTime currentDate = DateTime.Now;
      DateGenerator dateGenerator = new DateGenerator();
      String[] logFiles=Directory.GetFiles(pathLogFiles,"*.log");
			foreach(String logFile in logFiles)
			{
			  try
				{
          DateTime creationTime = File.GetCreationTime(logFile);
          DateTime lastAccessTime = File.GetLastAccessTime(logFile);
          DateTime earliestDate = lastAccessTime < creationTime? lastAccessTime : creationTime;
          int age = Math.Abs(dateGenerator.DaysBetweenActual(currentDate, earliestDate));
          Console.WriteLine($"[ExpireLogs ]{logFile} is {age} {(age>1?"days":"day")} old");
          if(age>=expiryDays)
          {
            File.Delete(logFile);
          }
				}
				catch(Exception exception)
        {
          Console.WriteLine($"{exception.ToString()}");
        }
			}
    }

    public static void ShowLogs(String pathLogFiles)
    {
      try
      {
        DateTime currentDate = DateTime.Now;
        DateGenerator dateGenerator = new DateGenerator();
        String[] logFiles=Directory.GetFiles(pathLogFiles,"*.log");
        MDTrace.WriteLine(LogLevel.DEBUG,$"[ShowLogs] Log folder : {pathLogFiles}");
        MDTrace.WriteLine(LogLevel.DEBUG,$"[ShowLogs] Found {logFiles.Length} log files.");
        foreach(String logFile in logFiles)
        {
          DateTime creationTime = File.GetCreationTime(logFile);
          DateTime lastWriteTime = File.GetLastWriteTime(logFile);
          DateTime lastAccessTime = File.GetLastAccessTime(logFile);
          DateTime earliestDate = lastAccessTime < creationTime? lastAccessTime : creationTime;
          FileAttributes attributes = File.GetAttributes(logFile);
          int age = Math.Abs(dateGenerator.DaysBetweenActual(currentDate, earliestDate));
          StringBuilder sb = new StringBuilder();
          sb.Append($"[ShowLogs] ");
          sb.Append($"'{logFile}'").Append(" ");
          sb.Append($"Age:").Append(age).Append(" ");
          sb.Append($"Created:").Append(creationTime.ToShortDateString()).Append(" ");
          sb.Append($"LastWrite:").Append(lastWriteTime.ToShortDateString()).Append(" ");
          sb.Append($"LastAccess:").Append(lastAccessTime.ToShortDateString()).Append(" ");
          sb.Append(FileAttributesToString(attributes));
          MDTrace.WriteLine(LogLevel.DEBUG,sb.ToString());
        }
      }
			catch(Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,$"{exception.ToString()}");
      }
		}

    private static String FileAttributesToString(FileAttributes attributes)
    {
      StringBuilder sb = new StringBuilder();
      List<String> attributesList = new List<String>();

      if(attributes==0)attributesList.Add("None");
      if(FileAttributes.ReadOnly == (attributes & FileAttributes.ReadOnly))attributesList.Add("ReadOnly");
      if(FileAttributes.System == (attributes & FileAttributes.System))attributesList.Add("System");
      if(FileAttributes.Hidden == (attributes & FileAttributes.Hidden))attributesList.Add("Hidden");
      if(FileAttributes.Directory == (attributes & FileAttributes.Directory))attributesList.Add("Directory");
      if(FileAttributes.Archive == (attributes & FileAttributes.Archive))attributesList.Add("Archive");
      if(FileAttributes.Device == (attributes & FileAttributes.Device))attributesList.Add("Device");
      if(FileAttributes.Normal == (attributes & FileAttributes.Normal))attributesList.Add("Normal");
      if(FileAttributes.Temporary == (attributes & FileAttributes.Temporary))attributesList.Add("Temporary");
      if(FileAttributes.SparseFile == (attributes & FileAttributes.SparseFile))attributesList.Add("SparseFile");
      if(FileAttributes.ReparsePoint == (attributes & FileAttributes.ReparsePoint))attributesList.Add("ReparsePoint");
      if(FileAttributes.Compressed == (attributes & FileAttributes.Compressed))attributesList.Add("Compressed");
      if(FileAttributes.Offline == (attributes & FileAttributes.Offline))attributesList.Add("Offline");
      if(FileAttributes.NotContentIndexed ==(attributes & FileAttributes.NotContentIndexed))attributesList.Add("NotContentIndexed");
      if(FileAttributes.Encrypted == (attributes & FileAttributes.Encrypted))attributesList.Add("Encrypted");
      if(FileAttributes.IntegrityStream == (attributes & FileAttributes.IntegrityStream))attributesList.Add("IntegrityStream");
      if(FileAttributes.NoScrubData == (attributes & FileAttributes.NoScrubData))attributesList.Add("NoScrubData");

      return Utility.ListToString(attributesList);
    }

    public static String Pad(string str, char filler, int length)
    {
      int stringLength = str.Length;
      if (stringLength >= length) return str;
      StringBuilder sb = new StringBuilder();

      while (stringLength < length)
      {
        sb.Append(filler);                                            
        stringLength++;
      }
      return sb.ToString() + str;
    } 
    public static bool Is64Bit()
    {
      if(IntPtr.Size.Equals(8))return true;
      return false; 
    }
    public static bool IsAdministrator()
    {
      return (new WindowsPrincipal(WindowsIdentity.GetCurrent())).IsInRole(WindowsBuiltInRole.Administrator);
    }  
    public static String ToUTF8(String str)
    {
      if(null==str)return str;
      return Encoding.UTF8.GetString(Encoding.Default.GetBytes(str));
    }
    public static String RemoveHtml(String strItem)
    {
      if(null==strItem)return null;
      String[] codes = { "&#x27;","&#187;" };
      if(null==strItem)return strItem;
      foreach (String code in codes)
      {
        strItem = strItem.Replace(code,"'");
      }
      strItem=strItem.Replace("&amp;","&");
      strItem=strItem.Replace(@"\\u0026","&");
      strItem=strItem.Replace("&#x2018;","'");
      strItem=strItem.Replace("&#x2019;","'");
      strItem=strItem.Replace("&#x2014;","-");
      strItem=strItem.Replace("&#x201C;",@"""");
      strItem=strItem.Replace("&#x201c;",@"""");
      strItem=strItem.Replace("&#x201D;",@"""");
      strItem=strItem.Replace("&#x201d;",@"""");
      strItem=strItem.Replace("&#x2013;","-");
      strItem=strItem.Replace("&#39;","'");
      return strItem;
    }
    public static String RemoveDivs(String strItem)
    {
      StringBuilder sb=new StringBuilder();
      bool inDiv=false;
      if(null==strItem)return strItem;
      for(int index=0;index<strItem.Length;index++)
      {
        char ch=strItem[index];
        if(ch.Equals('<'))inDiv=true;
        else if(ch.Equals('>'))inDiv=false;
        else if(!inDiv)sb.Append(ch);
      }
      return sb.ToString();
    }
    public static int CharToNum(char ch)
    {
      return (int)ch-48;
    }
    public static String RemoveCC(String item)
    {
      StringBuilder sb=new StringBuilder();
      foreach(char ch in item)
      {
        if(!Char.IsControl(ch)) sb.Append(ch);
      }
      return sb.ToString();
    }
    public static Stream StreamFromString(string s)
    {
      var stream=new MemoryStream();
      var writer=new StreamWriter(stream);
      writer.Write(s);
      writer.Flush();
      stream.Position=0;
      return stream;
    }
    public static String RemoveQuotes(String strItem)
    {
      if (String.IsNullOrEmpty(strItem)) return null;
      if(strItem.StartsWith("\""))strItem=strItem.Substring(1);
      if(strItem.EndsWith("\""))strItem=strItem.Substring(0,strItem.Length-1);
      return strItem;
    } 
    public static String BetweenString(String strItem, String strBegin, String strEnd)
    {
      if (null == strItem) return null;
      int index=-1;
      if(null==strBegin)index=0;
      else index = strItem.IndexOf(strBegin);
      if (-1 == index) return null;
      String str = null;
      if(null!=strBegin)str=strItem.Substring(index + strBegin.Length);
      else str=strItem;
      if(null==strEnd)return str;
      index = str.IndexOf(strEnd);
      if (-1 == index) return null;
      StringBuilder sb = new StringBuilder();
      for (int strIndex = 0; strIndex < str.Length; strIndex++)
      {
        if (index == strIndex) break;
        sb.Append(str[strIndex]);
      }
      return sb.ToString();
    }
    public static String RemoveAfter(String strItem, char charItem)
    {
      StringBuilder sb = new StringBuilder();
      for (int index = 0; index < strItem.Length; index++)
      {
        char ch = strItem[index];
        if (ch.Equals(charItem)) break;
        sb.Append(ch);
      }
      return sb.ToString();
    }
    public static bool OutOfRange(double value)
    {
      return value > 100000000000000000000.00 || value< -99999999999999999999.99;
    }
    public static String RemoveControlChars(String strItem)
    {
      StringBuilder sb=new StringBuilder();
      for(int index=0;index<strItem.Length;index++)
      {
        char ch=strItem[index];
        if(!char.IsControl(ch))sb.Append(ch);
      }
      return sb.ToString();
    }

    public static String GetPath(String strPathFileName)
    {
      int index=strPathFileName.LastIndexOf('\\');
      if (-1 == index) return null;
      String strPath = strPathFileName.Substring(0, index);
      return strPath;
    }

    public static String GetFileNameNoExtension(String pathFileName)
    {
      if(null==pathFileName)return null;
       pathFileName = Path.GetFileName(pathFileName);
      pathFileName=Utility.BetweenString(pathFileName,null,".");
      return pathFileName;
    }

    public static String KeepBefore(String strItem,String strKeepBefore)
    {
      int startPos=strItem.IndexOf(strKeepBefore);
      if(-1==startPos)return null;
      return strItem.Substring(0,startPos);
    }
    public static String KeepAfter(String strItem,String strKeepAfter)
    {
      int startPos=strItem.IndexOf(strKeepAfter);
      if(-1==startPos)return null;
      return strItem.Substring(startPos+strKeepAfter.Length);
    }
    public static String KeepAfterLast(String strItem,String strKeepAfter)
    {
      if(null==strItem)return null;
      int startPos=strItem.LastIndexOf(strKeepAfter);
      if(-1==startPos)return null;
      return strItem.Substring(startPos+strKeepAfter.Length);
    }
    public static String Find(String strItem,String search,char delimeter)
    {
      if(null==strItem)return null;
      bool foundDelimeter=false;
      StringBuilder sb=new StringBuilder();
      int startPos=strItem.LastIndexOf(search);
      if(-1==startPos)return null;
      startPos+=search.Length;
      for(;startPos<strItem.Length;startPos++)
      {
        char ch=strItem[startPos];
        if(ch.Equals(delimeter))
        {
          foundDelimeter=true;
          break;
        }
        sb.Append(ch);
      }
      if(!foundDelimeter)return null;
      return sb.ToString();
    }
    public static String FindFirst(String strItem,String search,char delimeter)
    {
      if(null==strItem)return null;
      bool foundDelimeter=false;
      StringBuilder sb=new StringBuilder();
      int startPos=strItem.IndexOf(search);
      if(-1==startPos)return null;
      startPos+=search.Length;
      for(;startPos<strItem.Length;startPos++)
      {
        char ch=strItem[startPos];
        if(ch.Equals(delimeter))
        {
          foundDelimeter=true;
          break;
        }
        sb.Append(ch);
      }
      if(!foundDelimeter)return null;
      return sb.ToString();
    }
    public static String AddQuotes(String item)
    {
      return "\"" + item + "\"";
    }
    public static long DateToLong(DateTime date)
    {
      int year = date.Year;
      int month = date.Month;
      int day = date.Day;
      return (year * 10000) + (month * 100) + day;
    }
    public static DateTime LongToDate(long longDate)
    {
      int year = (int)(longDate / 10000);
      int month = ((int)longDate / 100) - year * 100;
      int day = (int)(longDate - ((int)(longDate / 100)) * 100);
      return new DateTime(year, month, day);
    }
    public static String DayOfWeekToString(DayOfWeek dayOfWeek)
    {
      switch(dayOfWeek)
      {
        case System.DayOfWeek.Monday: return "Monday";
        case System.DayOfWeek.Tuesday: return "Tuesday";
        case System.DayOfWeek.Wednesday: return "Wednesday";
        case System.DayOfWeek.Thursday: return "Thursday";
        case System.DayOfWeek.Friday: return "Friday";
        case System.DayOfWeek.Saturday: return "Saturday";
        case System.DayOfWeek.Sunday: return "Sunday";
        default: return "";
      }
    }
    public static String DateTimeToStringMMMM(DateTime dateTime)
    {
      if (Utility.IsEpoch(dateTime)) return "";
      return dateTime.ToString("MMMM");
    }
    public static String DateTimeToStringMMM(DateTime dateTime)
    {
      if (Utility.IsEpoch(dateTime)) return "";
      return dateTime.ToString("MMM");
    }
    public static String DateTimeToStringHHMMSS(DateTime dateTime)
    {
      if (Utility.IsEpoch(dateTime)) return "";
      return dateTime.ToString("HH:mm:ss");
    }
    public static String DateTimeToStringMMSDDSYYYY(DateTime dateTime)
    {
      if (Utility.IsEpoch(dateTime)) return "";
      return dateTime.ToString("MM/dd/yyyy");
    }
    public static String DateTimeToStringMMSDDSYYYYHHMMSS(DateTime dateTime)
    {
      if (Utility.IsEpoch(dateTime)) return "";
      return dateTime.ToString("MM/dd/yyyy hh:mm:ss");
    }
    public static String DateTimeToStringMMHDDHYYYY(DateTime dateTime)
    {
      if (Utility.IsEpoch(dateTime)) return "";
      return dateTime.ToString("MM-dd-yyyy");
    }
    public static String DateTimeToStringYYYYHMMHDD(DateTime dateTime)
    {
      if (Utility.IsEpoch(dateTime)) return "";
      return dateTime.ToString("yyyy-MM-dd");
    }
    public static String DateTimeToStringYYYYHMMHDDHHMMSS(DateTime dateTime)
    {
      if (Utility.IsEpoch(dateTime)) return "";
      return dateTime.ToString("yyyy-MM-dd hh:mm:ss");
    }
    public static String DateTimeToStringYYYYHMMHDDHHMMSSTT(DateTime dateTime)
    {
      if(Utility.IsEpoch(dateTime)) return "";
      return dateTime.ToString("yyyy-MM-dd hh:mm:ss tt");
    }
    public static String DateTimeToStringYYYYMMDDMMSSTT(DateTime dateTime)
    {
      if(Utility.IsEpoch(dateTime)) return "";
      return dateTime.ToString("yyyyMMddhhmmsstt");
    }
    public static String DateTimeToStringYYYYMMDD(DateTime dateTime)
    {
      if (Utility.IsEpoch(dateTime)) return "";
      return dateTime.ToString("yyyyMMdd");
    }
    public static String AsteriskForString(String str)
    {
      StringBuilder sb = new StringBuilder();
      int length = str.Length;
      for (int index = 0; index < length; index++) sb.Append("*");
      return sb.ToString();
    }
    public static String FormatNumber(double number)
    {
      StringBuilder sb=new StringBuilder();
      if (double.NaN.Equals(number))sb.Append("N/A");
      else sb.Append(String.Format("{0:0.000}", number));
      return sb.ToString();
    }
    public static String FormatNumber(double number,int places,bool commas=false)
    {
      StringBuilder sb = new StringBuilder();

      StringBuilder formatString=new StringBuilder();
      if (commas&&Math.Abs(number)>=1000.00) formatString.Append("{0:0,0.");
      else formatString.Append("{0:0.");
      for(int index=0;index<places;index++)formatString.Append("0");
      formatString.Append("}");
      if (double.NaN.Equals(number)) sb.Append("N/A");
      else sb.Append(String.Format(formatString.ToString(), number));
      return sb.ToString();
    }
    public static String FormatCurrency(double number)
    {
      StringBuilder sb=new StringBuilder();
      if (double.NaN.Equals(number))sb.Append("N/A");
      else sb.Append(String.Format("{0:C}", number));
      return sb.ToString();
    }


    public static String FormatPrice(double price)
    {
      return FormatCurrency(price, 3);
    }

    public static String FormatCurrency(double number,int decimals)
    {
      StringBuilder sb=new StringBuilder();
      String currencyFormat="{0:C"+decimals+"}";
      if (double.NaN.Equals(number))sb.Append("N/A");
      else sb.Append(String.Format(currencyFormat, number));
      return sb.ToString();
    }
    public static String FormatPercent(double number)
    {
      StringBuilder sb = new StringBuilder();
      if (double.NaN.Equals(number)) sb.Append("N/A");
      else sb.Append(String.Format("{0:P}", number));
      return sb.ToString();
    }
    public static String FormatPercent(double number,int places)
    {
      StringBuilder sb=new StringBuilder();
      String formatString="{0:P"+places+"}";
      if(double.NaN.Equals(number)) sb.Append("N/A");
      else sb.Append(String.Format(formatString,number));
      return sb.ToString();
    }
    public static String ConformDate(String strDate)
    {
      String[] elements=strDate.Split(' ');
      if(elements.Length<3)return strDate;
      return elements[0]+" "+elements[1]+" "+elements[2];
    }
    public static DateTime ParseDate(String strDate)
    {
      System.Globalization.CultureInfo cultureInfo = new System.Globalization.CultureInfo("en-US");
      String[] formats=new[] { "MM/dd/yyyy HH:MM tt", "yyyy-MM-dd","yy-MM-dd","yyyy-MM-dd hh:mm:ss tt","dddd, MMMM dd","MMM dd yyyy","yyyy-MM","ddd, MMM. d","ddd, MMM. dd","yyyy/MM/dd","M-d-yyyy","dd-MM-yyyy","MM-dd-yyyy","M.d.yyyy","dd.MM.yyyy","MM.dd.yyyy","yyyyMMdd" }.Union(cultureInfo.DateTimeFormat.GetAllDateTimePatterns()).ToArray();
      strDate = strDate.Trim();
      DateTime dateTime=DateTime.ParseExact(strDate, formats, cultureInfo, DateTimeStyles.AssumeLocal);
      return dateTime;
    }
    public static double ParsePercent(String strPercent)
    {
      if (null == strPercent) return double.NaN;
      strPercent = strPercent.Replace("%", null);
      try { return double.Parse(strPercent)/100.00; }
      catch (Exception) { return double.NaN; }
    }
    public static double ParseCurrency(String strNumber)
    {
      if (null == strNumber) return double.NaN;
      if(Constants.CONST_DASHES.Equals(strNumber))return double.NaN;
      strNumber = strNumber.Replace("$", null);
      strNumber = strNumber.Replace(",", null);
      strNumber = strNumber.Replace("(", "-");
      strNumber = strNumber.Replace(")", null);
      if (strNumber.Equals("")) return double.NaN;
      try { return double.Parse(strNumber); }
      catch (Exception) { return double.NaN; }
    }
    public static String FormatCurrencyWithQuotes(double number)
    {
      return AddQuotes(FormatCurrency(number));
    }
    public static String FormatDates(DateTime d1, DateTime d2)
    {
      StringBuilder sb=new StringBuilder();
      sb.Append(Utility.DateTimeToStringMMSDDSYYYY(d1)).Append("-");
      sb.Append(Utility.DateTimeToStringMMSDDSYYYY(d2));
      return sb.ToString();
    }
    public static String TrimToSpace(String strString)
    {
      if (null == strString) return strString;
      StringBuilder sb = new StringBuilder();
      for (int index = 0; index < strString.Length; index++)
      {
        char ch=strString[index];
        if (' '.Equals(ch)) break;
        sb.Append(ch);
      }
      return sb.ToString();
    }
    public static String BooleanToYesNoString(bool booleanValue)
    {
      return booleanValue ? "Yes" : "No";
    }
    public static bool IsEpoch(DateTime dateTime)
    {
      return dateTime.Equals(epoch);
    }
    public static DateTime Epoch
    {
      get { return epoch; }
    }
    public static TimeSpan OneDay
    {
      get{return oneDay;}
    }
    public static String ListToString(List<String> list,char separator=',')
    {
      StringBuilder sb=new StringBuilder();
      if (null == list || 0 == list.Count) return null;
      for(int index=0;index<list.Count;index++)
      {
        sb.Append(list[index]);
        if(index<list.Count-1)sb.Append(separator);
      }
      return sb.ToString();
    }
    public static List<String> ToList(String items,char separator=',')
    {
      List<String> list = items.Split(separator).ToList<String>();
      list=(from String str in list where !String.IsNullOrEmpty(str) select str.Trim()).ToList<String>();
      return list;
    }
    public static String FromList(List<String> items,String postFix=",")
    {
      StringBuilder sb=new StringBuilder();
      for(int index=0;index<items.Count;index++)
      {
        sb.Append(items[index]);
        if(index<items.Count-1)sb.Append(postFix);
      }
      return sb.ToString();
    }
    public static byte[] Compress(String strString)
    {
      MemoryStream outputStream = null;
      GZipStream compressionStream = null;
      try
      {
        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(strString);
        outputStream = new MemoryStream();
        compressionStream = new GZipStream(outputStream, CompressionMode.Compress, true);
        compressionStream.Write(bytes, 0, bytes.Length);
        compressionStream.Close();
        compressionStream = null;
        byte[] outputBytes = outputStream.ToArray();
        outputStream.Close();
        outputStream = null;
        return outputBytes;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
        return null;
      }
      finally
      {
        if (null != compressionStream)
        {
          compressionStream.Close();
          compressionStream = null;
        }
        if (null != outputStream)
        {
          outputStream.Close();
          outputStream = null;
        }
      }
    }
    public static String Decompress(byte[] compressedBytes)
    {
      MemoryStream compressedStream = new MemoryStream(compressedBytes);
      GZipStream decompressionStream = new GZipStream(compressedStream, CompressionMode.Decompress,true);
      MemoryStream outputStream=new MemoryStream();
      try
      {
        byte[] decompressedBytesBuffer = new byte[4096];
        int count = 0;
        while (true)
        {
          count = decompressionStream.Read(decompressedBytesBuffer, 0, decompressedBytesBuffer.Length);
          if (count > 0) outputStream.Write(decompressedBytesBuffer, 0, count);
          else break;
        }
        decompressionStream.Close();
        compressedStream.Close();
        String strDecompressed = System.Text.Encoding.UTF8.GetString(outputStream.ToArray());
        outputStream.Close();
        outputStream = null;
        compressedStream = null;
        decompressionStream = null;
        return strDecompressed;
      }
      catch (Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,exception);
        return null;
      }
      finally
      {
        if (null != outputStream)
        {
          outputStream.Close();
          outputStream = null;
        }
        if (null != decompressionStream)
        {
          decompressionStream.Close();
          decompressionStream = null;
        }
        if (null != compressedStream)
        {
          compressedStream.Close();
          compressedStream = null;
        }
      }
    }
    public static void LaunchBrowserSearch(String searchTerm)
    {
      Process.Start("https://www.google.com/search?q="+Uri.EscapeDataString(searchTerm)+"/");
    }
    public static bool IsZeroOrNaN(double value)
    {
      return IsNaN(value)||IsZero(value);
    }
    private static bool IsZero(double value)
    {
      if(value==0.00)return true;
      return false;
    }
    private static bool IsNaN(double value)
    {
      return double.IsNaN(value);
    }
    public static bool DeleteFile(String pathFileName)
    {
      if(!File.Exists(pathFileName))return false;
      try{File.Delete(pathFileName);}catch(Exception){return false;}
      return true;
    }

    public static bool CopyFile(String pathSrcFileName,String pathDstFileName)
    {
      if(!File.Exists(pathSrcFileName))return false;
      try{File.Copy(pathSrcFileName,pathDstFileName);}catch(Exception){return false;}
      return true;
    }

    private static DateTime GetRunDate(String strPathFileName)
    {
      DateTime runDate=DateTime.Now.Date;
      DateGenerator dateGenerator=new DateGenerator();
      StreamWriter streamWriter=null;
      StreamReader streamReader=null;

      try
      {
        if(!File.Exists(strPathFileName))
        {
          streamWriter=File.CreateText(strPathFileName);
          streamWriter.WriteLine(Utility.DateTimeToStringMMHDDHYYYY(runDate));
          streamWriter.Flush();
          streamWriter.Close();
          streamWriter=null;
          return runDate;
        }
        streamReader=File.OpenText(strPathFileName);
        String strLine=streamReader.ReadLine();
        streamReader.Close();
        streamReader=null;
        runDate=Utility.ParseDate(strLine);
        if(dateGenerator.DaysBetweenActual(runDate,DateTime.Now)>5)
        {
          File.Delete(strPathFileName);
          runDate=DateTime.Now.Date;
          streamWriter=File.CreateText(strPathFileName);
          streamWriter.WriteLine(Utility.DateTimeToStringMMHDDHYYYY(runDate));
          streamWriter.Flush();
          streamWriter.Close();
          streamWriter=null;
          return runDate;
        }
        return runDate;
      }
      catch(Exception exception)
      {
        MDTrace.WriteLine(LogLevel.DEBUG,String.Format("GetRunDate:{0}",exception.ToString()));
        return runDate;
      }
      finally
      {
        if(null!=streamWriter)streamWriter.Close();
        if(null!=streamReader)streamReader.Close();
      }
    }
  }
}