package com.bernard.mcqinator.inutil;

import android.util.Log;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * @author Mysaa
 * @date on 22/07/17.
 */

public class ArrayInutil {

    public static <X> List<X> asize(List<X> items, int length, Integer[] failSumsArray, int failSum, Random r){
        if(Arrays.class.equals(items.getClass().getEnclosingClass()))
            items = new ArrayList<>(items);
        return asizeP(items,length,failSumsArray,failSum,r);
    }

    public static <X> List<X> asize(X[] items,int length,Integer[] failSumsArray,int failSum,Random r){
        return asize(Arrays.asList(items),length,failSumsArray,failSum,r);
    }

    private static <X> List<X> asizeP(List<X> items,int length,Integer[] failSumsArray,int failSum,Random r){
        Log.d("asizement","asizeP("+items.toString()+","+length+","+Arrays.toString(failSumsArray)+","+failSum+",random)");
        ArrayList<Integer> failSums = new ArrayList<>(Arrays.asList(failSumsArray));
        ArrayList<X> finalItems = new ArrayList<>();
        if(items.size() <= 0)Log.e("ArrayInutil","List empty !"+items.add(null));
        if(items.size() < length){
            int n = (int) Math.floor(length / items.size());
            for (int i = 0; i < n; i++)
                finalItems.addAll(items);
        }
        int currentFailSum = failSum;
        while(finalItems.size()<length){
            Log.d("Condition",finalItems.size()+"<"+length);
            int ran = r.nextInt(currentFailSum + 1);
            int total = 0;
            for (int i = 0; i < items.size(); i++) {
                total+=failSums.get(i);
                if(total >= ran){
                    currentFailSum -= failSums.get(i);
                    finalItems.add(items.get(i));
                    failSums.remove(i);
                    items.remove(i);
                    break;
                }
            }
        }
        Collections.shuffle(finalItems,r);
        return finalItems;
    }

    public static <X> Map<X,Integer> count(List<X> items){
        Map<X,Integer> out = new HashMap<>();
        for (X x:items) {
            X key = null;
            for (X k:out.keySet())
                if(x.equals(k))
                    key = k;
            if (key == null)
                out.put(x, 1);
            else
                out.put(key, out.get(x) + 1);
        }
        return out;
    }

    public static Long[] toObjectArray(long[] array){
        Long[] out = new Long[array.length];
        for (int i = 0; i < out.length; i++)
            out[i] = array[i];
        return out;
    }

    public static Integer[] toObjectArray(int[] array){
        Integer[] out = new Integer[array.length];
        for (int i = 0; i < out.length; i++)
            out[i] = array[i];
        return out;
    }

    public static Long[][] toObjectArray(long[][] array){
        Long[][] out = new Long[array.length][];
        for (int i = 0; i < out.length; i++)
            out[i] = toObjectArray(array[i]);
        return out;
    }

    public static Integer[][] toObjectArray(int[][] array){
        Integer[][] out = new Integer[array.length][];
        for (int i = 0; i < out.length; i++)
            out[i] = toObjectArray(array[i]);
        return out;
    }

    public static long[] toPrimitiveArray(Long[] array){
        long[] out = new long[array.length];
        for (int i = 0; i < out.length; i++)
            out[i] = array[i];
        return out;
    }

    public static int[] toPrimitiveArray(Integer[] array){
        int[] out = new int[array.length];
        for (int i = 0; i < out.length; i++)
            out[i] = array[i];
        return out;
    }

    public static long[][] toPrimitiveArray(Long[][] array){
        long[][] out = new long[array.length][];
        for (int i = 0; i < out.length; i++)
            out[i] = toPrimitiveArray(array[i]);
        return out;
    }

    public static int[][] toPrimitiveArray(Integer[][] array){
        int[][] out = new int[array.length][];
        for (int i = 0; i < out.length; i++)
            out[i] = toPrimitiveArray(array[i]);
        return out;
    }

    public static <T> boolean inArray  (T needle, T[] haystack){
        for(T item : haystack)
            if(item.equals(needle))return true;
        return false;
    }

    public static Integer[] range (int low, int high){
        Integer[] result = new Integer[high-low];
        for(int i = 0;i<high-low;i++)
            result[i] = low + i;
        return result;
    }

    public static <T> int indexOf(T[] haystack, T needle) {
        for (int i = 0; i < haystack.length; i++) {
            if(haystack[i] != null && haystack[i].equals(needle))
                return i;
        }
        return -1;
    }

    public static <T> void removeIndex(T[] array, int index) {
        System.arraycopy(array,index+1,array,index, array.length-index);
    }



}
