using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.IO;
using System.Linq;

namespace QC.CTDS.DM.SharedLibrary;

public static class Extensions
{
	public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
	{
		if (enumerable == null)
		{
			return;
		}
		foreach (T item in enumerable)
		{
			action?.Invoke(item);
		}
	}

	public static void RemoveAll<T>(this ObservableCollection<T> observableCollection, Predicate<T> match)
	{
		List<T> list = observableCollection.ToList().FindAll(match);
		list.ForEach(delegate(T matchItem)
		{
			observableCollection.Remove(matchItem);
		});
	}

	public static void AddRange<T>(this SortedSet<T> sortedSet, IEnumerable<T> collection)
	{
		collection.ForEach(delegate(T col)
		{
			sortedSet.Add(col);
		});
	}

	public static void AddRangeDistinct<T>(this IList<T> rangeSet, IList<T> newItems)
	{
		foreach (T newItem in newItems)
		{
			if (!rangeSet.Contains(newItem))
			{
				rangeSet.Add(newItem);
			}
		}
	}

	public static string ToBaseX(this double doubleVal, string baseIndicator)
	{
		int num = Convert.ToInt32(doubleVal);
		string result = string.Empty;
		if (int.TryParse(baseIndicator, out var result2))
		{
			result = ((result2 != 16) ? Convert.ToString(num, result2) : ("0x" + Convert.ToString(num, result2)));
			result = result.ToUpper();
		}
		return result;
	}

	public static void Merge<TKey, TValue>(this IDictionary<TKey, TValue> parentDict, IDictionary<TKey, TValue> toMergeDict)
	{
		if (toMergeDict == null)
		{
			return;
		}
		if (parentDict == null)
		{
			parentDict = new Dictionary<TKey, TValue>();
		}
		foreach (KeyValuePair<TKey, TValue> item in toMergeDict)
		{
			if (!parentDict.ContainsKey(item.Key))
			{
				parentDict.Add(item.Key, item.Value);
			}
		}
	}

	public static object[][] To2dArray(this DataTable tbl)
	{
		object[][] array = null;
		if (tbl != null)
		{
			int count = tbl.Columns.Count;
			int count2 = tbl.Rows.Count;
			array = new object[count2 + 1][];
			array[0] = new object[count];
			for (int i = 0; i < count; i++)
			{
				array[0][i] = tbl.Columns[i].ColumnName;
			}
			for (int j = 0; j < count2; j++)
			{
				array[j + 1] = tbl.Rows[j].ItemArray;
			}
		}
		return array;
	}

	public static double StandardDeviation(this IEnumerable<double> values)
	{
		double num = 0.0;
		double num2 = values.Avg();
		foreach (double value in values)
		{
			double num3 = value;
			double num4 = num3 - num2;
			num += num4 * num4;
		}
		double num5 = ((values.Count() != 1) ? Math.Sqrt(num / (double)(values.Count() - 1)) : 0.0);
		if (double.IsNaN(num5))
		{
			num5 = 0.0;
		}
		return num5;
	}

	public static double Avg(this IEnumerable<double> values)
	{
		if (values.Count() > 0)
		{
			double sum = 0.0;
			values.ForEach(delegate(double val)
			{
				sum += val;
			});
			return Math.Round(sum, 5) / (double)values.Count();
		}
		return 0.0;
	}

	public static double Median(this IEnumerable<double> enumerable)
	{
		double num = 0.0;
		int num2 = enumerable.Count();
		if (num2 > 2)
		{
			int num3 = (num2 - 1) / 2;
			if (num2 % 2 != 0)
			{
				return enumerable.ElementAt(num3);
			}
			return (enumerable.ElementAt(num3) + enumerable.ElementAt(num3 + 1)) / 2.0;
		}
		return num2 switch
		{
			2 => (enumerable.ElementAt(0) + enumerable.ElementAt(1)) / 2.0, 
			1 => enumerable.ElementAt(0), 
			_ => double.NaN, 
		};
	}

	public static void WriteToCSV(this DataTable tbl, string filePath, bool includeHeaders = true, string delimiter = ",")
	{
		if (tbl == null)
		{
			throw new ArgumentException("Table is null");
		}
		if (string.IsNullOrEmpty(filePath))
		{
			throw new ArgumentException("filepath is null or empty");
		}
		if (tbl.Rows.Count <= 0)
		{
			return;
		}
		using StreamWriter streamWriter = new StreamWriter(filePath, append: false);
		delimiter = FormatDelimiter(delimiter);
		DelimiterWriter dw = new DelimiterWriter(streamWriter, delimiter);
		if (includeHeaders)
		{
			List<string> list = new List<string>();
			foreach (DataColumn column in tbl.Columns)
			{
				list.Add(column.ColumnName);
			}
			dw.WriteData(list);
		}
		tbl.AsEnumerable().ForEach(delegate(DataRow dataRow)
		{
			dw.WriteData(dataRow.ItemArray);
		});
		streamWriter.Close();
	}

	private static string FormatDelimiter(string delimiterStr)
	{
		string result = delimiterStr;
		if (!string.IsNullOrEmpty(delimiterStr))
		{
			if (delimiterStr == "\\t")
			{
				result = "\t";
			}
			else if (delimiterStr == "\\r")
			{
				result = "\r";
			}
		}
		return result;
	}

	public static void WriteToCSV<T>(this Table<T> tbl, string filePath, bool includeHeaders = true, string delimiter = ",")
	{
		if (tbl == null)
		{
			throw new ArgumentException("Table is null");
		}
		if (string.IsNullOrEmpty(filePath))
		{
			throw new ArgumentException("filepath is null or empty");
		}
		if (tbl.RowCount <= 0)
		{
			return;
		}
		using StreamWriter streamWriter = new StreamWriter(filePath, append: false);
		delimiter = FormatDelimiter(delimiter);
		DelimiterWriter delimiterWriter = new DelimiterWriter(streamWriter, delimiter);
		if (includeHeaders)
		{
			List<string> list = new List<string>();
			for (int i = 0; i < tbl.ColumnCount; i++)
			{
				list.Add(tbl.GetColumnName(i));
			}
			delimiterWriter.WriteData(list);
		}
		for (int j = 0; j < tbl.RowCount; j++)
		{
			List<T> list2 = new List<T>();
			for (int k = 0; k < tbl.ColumnCount; k++)
			{
				list2.Add(tbl.GetValue(j, k));
			}
			delimiterWriter.WriteData(list2);
		}
		streamWriter.Close();
	}
}
