using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace U.ListOperations
{
    public class UArray
    {
        // sameValues - 1D
        public static T[] sameValues<T>(T val, int n) { T[] arr = new T[n]; for (int i = 0; i < n; i++) { arr[i] = val; } return arr; }
        public static string[] sameValues(string val, int n) { string[] arr = new string[n]; for (int i = 0; i < n; i++) { arr[i] = val; } return arr; }
        public static double[] sameValues(double val, int n) { double[] arr = new double[n]; for (int i = 0; i < n; i++) { arr[i] = val; } return arr; }
        public static int[] sameValues(int val, int n) { int[] arr = new int[n]; for (int i = 0; i < n; i++) { arr[i] = val; } return arr; }

        // sameValues - 2D
        public static T[,] sameValues<T>(T val, int n1, int n2) { T[,] arr = new T[n1, n2]; for (int i = 0; i < n1; i++) { for (int j = 0; j < n2; j++) { arr[i, j] = val; } } return arr; }
        public static string[,] sameValues(string val, int n1, int n2) { string[,] arr = new string[n1, n2]; for (int i = 0; i < n1; i++) { for (int j = 0; j < n2; j++) { arr[i, j] = val; } } return arr; }
        public static double[,] sameValues(double val, int n1, int n2) { double[,] arr = new double[n1, n2]; for (int i = 0; i < n1; i++) { for (int j = 0; j < n2; j++) { arr[i, j] = val; } } return arr; }
        public static int[,] sameValues(int val, int n1, int n2) { int[,] arr = new int[n1, n2]; for (int i = 0; i < n1; i++) { for (int j = 0; j < n2; j++) { arr[i, j] = val; } } return arr; }

        // clone
        public static string[] clone(string[] array) { int n = array.Length; string[] r = new string[n]; for (int i = 0; i < n; i++) { r[i] = array[i]; } return r; }
        public static double[] clone(double[] array) { int n = array.Length; double[] r = new double[n]; for (int i = 0; i < n; i++) { r[i] = array[i]; } return r; }
        public static int[] clone(int[] array) { int n = array.Length; int[] r = new int[n]; for (int i = 0; i < n; i++) { r[i] = array[i]; } return r; }
        public static long[] clone(long[] array) { long n = array.Length; long[] r = new long[n]; for (int i = 0; i < n; i++) { r[i] = array[i]; } return r; }
        public static string[,] clone(string[,] matrix) { int n1 = matrix.GetLength(0); int n2 = matrix.GetLength(1); string[,] m = new string[n1, n2]; for (int i = 0; i < n1; i++) { for (int j = 0; j < n2; j++) { m[i, j] = matrix[i, j]; } } return m; }
        public static double[,] clone(double[,] matrix) { int n1 = matrix.GetLength(0); int n2 = matrix.GetLength(1); double[,] m = new double[n1, n2]; for (int i = 0; i < n1; i++) { for (int j = 0; j < n2; j++) { m[i, j] = matrix[i, j]; } } return m; }
        public static int[,] clone(int[,] matrix) { int n1 = matrix.GetLength(0); int n2 = matrix.GetLength(1); int[,] m = new int[n1, n2]; for (int i = 0; i < n1; i++) { for (int j = 0; j < n2; j++) { m[i, j] = matrix[i, j]; } } return m; }
        public static long[,] clone(long[,] matrix) { int n1 = matrix.GetLength(0); int n2 = matrix.GetLength(1); long[,] m = new long[n1, n2]; for (int i = 0; i < n1; i++) { for (int j = 0; j < n2; j++) { m[i, j] = matrix[i, j]; } } return m; }

        // Equals
        public static bool equals<T>(T[] array1, T[] array2) { int n1 = array1.Length; int n2 = array2.Length; if (n1 != n2) { return false; } for (int i = 0; i < n1; i++) { if (!array1[i].Equals(array2[i])) { return false; } } return true; }
        public static bool equals(string[] array1, string[] array2) { int n1 = array1.Length; int n2 = array2.Length; if (n1 != n2) { return false; } for (int i = 0; i < n1; i++) { if (!array1[i].Equals(array2[i])) { return false; } } return true; }
        public static bool equals(double[] array1, double[] array2) { int n1 = array1.Length; int n2 = array2.Length; if (n1 != n2) { return false; } for (int i = 0; i < n1; i++) { if (!array1[i].Equals(array2[i])) { return false; } } return true; }
        public static bool equals(int[] array1, int[] array2) { int n1 = array1.Length; int n2 = array2.Length; if (n1 != n2) { return false; } for (int i = 0; i < n1; i++) { if (!array1[i].Equals(array2[i])) { return false; } } return true; }

        // isSubsetOf
        public static bool isSubsetOf<T>(T[] subset, T[] set) { if (subset.Length == 0 && set.Length == 0) { return true; } foreach (T item in subset) { if (!set.Contains(item)) { return false; } } return true; }
        public static bool isSubsetOf(string[] subset, string[] set) { if (subset.Length == 0 && set.Length == 0) { return true; } foreach (string item in subset) { if (!set.Contains(item)) { return false; } } return true; }
        public static bool isSubsetOf(double[] subset, double[] set) { if (subset.Length == 0 && set.Length == 0) { return true; } foreach (double item in subset) { if (!set.Contains(item)) { return false; } } return true; }
        public static bool isSubsetOf(int[] subset, int[] set) { if (subset.Length == 0 && set.Length == 0) { return true; } foreach (int item in subset) { if (!set.Contains(item)) { return false; } } return true; }

        // getSubset
        public static T[] getSubset<T>(T[] set, List<int> subsetItemIds) { T[] subset = new T[subsetItemIds.Count]; for (int i = 0; i < subsetItemIds.Count; i++) { subset[i] = set[subsetItemIds[i]]; } return subset; }
        public static string[] getSubset(string[] set, List<int> subsetItemIds) { string[] subset = new string[subsetItemIds.Count]; for (int i = 0; i < subsetItemIds.Count; i++) { subset[i] = set[subsetItemIds[i]]; } return subset; }
        public static double[] getSubset(double[] set, List<int> subsetItemIds) { double[] subset = new double[subsetItemIds.Count]; for (int i = 0; i < subsetItemIds.Count; i++) { subset[i] = set[subsetItemIds[i]]; } return subset; }
        public static int[] getSubset(int[] set, List<int> subsetItemIds) { int[] subset = new int[subsetItemIds.Count]; for (int i = 0; i < subsetItemIds.Count; i++) { subset[i] = set[subsetItemIds[i]]; } return subset; }

        // DataTable
        public static string[,] getDtRows(DataTable dataTable, bool includeHeader) { string[,] r; if (includeHeader) { r = new string[dataTable.Rows.Count + 1, dataTable.Columns.Count]; } else { r = new string[dataTable.Rows.Count, dataTable.Columns.Count]; } int itr = 0; if (includeHeader) { for (int i = 0; i < dataTable.Columns.Count; i++) { r[0, i] = dataTable.Columns[i].ColumnName; } itr = itr + 1; } for (int i = 0; i < dataTable.Rows.Count; i++) { for (int j = 0; j < dataTable.Columns.Count; j++) { r[itr + i, j] = dataTable.Rows[i][j].ToString(); } } return r; }
        public static string[] getDtHeaders(DataTable dataTable) { string[] r = new string[dataTable.Columns.Count]; for (int i = 0; i < dataTable.Columns.Count; i++) { r[i] = dataTable.Columns[i].ColumnName; } return r; }
        public static string[] getDtColumnString(DataTable dataTable, int columnNumber) { string[] r = new string[dataTable.Rows.Count]; for (int i = 0; i < dataTable.Rows.Count; i++) { r[i] = dataTable.Rows[i][columnNumber].ToString(); } return r; }
        public static double[] getDtColumnDouble(DataTable dataTable, int columnNumber) { double[] r = new double[dataTable.Rows.Count]; for (int i = 0; i < dataTable.Rows.Count; i++) { r[i] = Convert.ToDouble(dataTable.Rows[i][columnNumber].ToString()); } return r; }
        public static short[] getDtColumnInt16(DataTable dataTable, int columnNumber) { short[] r = new short[dataTable.Rows.Count]; for (int i = 0; i < dataTable.Rows.Count; i++) { r[i] = Convert.ToInt16(dataTable.Rows[i][columnNumber].ToString()); } return r; }
        public static int[] getDtColumnInt32(DataTable dataTable, int columnNumber) { int[] r = new int[dataTable.Rows.Count]; for (int i = 0; i < dataTable.Rows.Count; i++) { r[i] = Convert.ToInt32(dataTable.Rows[i][columnNumber].ToString()); } return r; }
        public static long[] getDtColumnInt64(DataTable dataTable, int columnNumber) { long[] r = new long[dataTable.Rows.Count]; for (int i = 0; i < dataTable.Rows.Count; i++) { r[i] = Convert.ToInt64(dataTable.Rows[i][columnNumber].ToString()); } return r; }


        // indexOfMin
        public static int indexOfMin(double[] array) { double min = double.MaxValue; int x = -1; for (int i = 0; i < array.Length; i++) { if (array[i] < min) { min = array[i]; x = i; } } return x; }
        public static int indexOfMin(int[] array) { int min = Int32.MaxValue; int x = -1; for (int i = 0; i < array.Length; i++) { if (array[i] < min) { min = array[i]; x = i; } } return x; }
        public static int indexOfMin(long[] array) { long min = Int64.MaxValue; int x = -1; for (int i = 0; i < array.Length; i++) { if (array[i] < min) { min = array[i]; x = i; } } return x; }


        // toArray
        public static T[] toArray<T>(List<T> list) { int n = list.Count; T[] r = new T[n]; for (int i = 0; i < n; i++) { r[i] = list[i]; } return r; }
        public static int[] toArray(List<int> list) { int n = list.Count; int[] r = new int[n]; for (int i = 0; i < n; i++) { r[i] = list[i]; } return r; }
        public static double[] toArray(List<double> list) { int n = list.Count; double[] r = new double[n]; for (int i = 0; i < n; i++) { r[i] = list[i]; } return r; }
        public static string[] toArray(List<string> list) { int n = list.Count; string[] r = new string[n]; for (int i = 0; i < n; i++) { r[i] = list[i]; } return r; }

        


        // try to delete
        public class ValueAndIndex
        {
            private double value;
            private int index;
            public double getValue() { return this.value; }
            public int getIndex() { return this.index; }

            public void setMinValue(double[] array) { value = double.MaxValue; index = -1; for (int i = 0; i < array.Length; i++) { if (array[i] < value) { value = array[i]; index = i; } } }
            public void setMinValueOfRow(double[,] matrix, int rowNumber) { value = double.MaxValue; index = -1; for (int i = 0; i < matrix.Length; i++) { if (matrix[rowNumber, i] < value) { value = matrix[rowNumber, i]; index = i; } } }

        }
    }
}
