package ca.recrown.islandsurvivalcraft.utilities;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

import ca.recrown.islandsurvivalcraft.utilities.datatypes.Point2;

public class GeneralUtilities {
    public final static int CHUNK_SIZE = 16;
    public final static ExecutorService ISC_EXECUTOR_ALPHA = Executors.newFixedThreadPool(1, createThreadFactory("ALPHA", Thread.NORM_PRIORITY + 1));
    public final static ExecutorService ISC_EXECUTOR_BETA = Executors.newFixedThreadPool(2, createThreadFactory("BETA", Thread.NORM_PRIORITY));

    public static <K, V> HashMap<V, ArrayList<K>> invertHashMap(HashMap<K, V> hashMap) {
        HashMap<V, ArrayList<K>> res = new HashMap<>();
        for (Entry<K, V> entry : hashMap.entrySet()) {
            if (!res.containsKey(entry.getValue())) {
                ArrayList<K> l = new ArrayList<K>();
                l.add(entry.getKey());
                res.put(entry.getValue(), l);
            } else {
                res.get(entry.getValue()).add(entry.getKey());
            }
        }
        return res;
    }

    public static int addMagnitude(int value, int add) {
        boolean negative = false;
        if (value < 0) negative = true;
        int res = Math.abs(value) + add;
        return negative ? - res : res;
    }

    public static Point2 worldToChunkCoordinates(int x, int y) {
        int xRes = 0;
        if (x < 0) {
            xRes = (int) Math.floor((float) x / CHUNK_SIZE);
        } else {
            xRes = x / CHUNK_SIZE;
        }
        int yRes = 0;
        if (y < 0) {
            yRes = (int) Math.floor((float) y / CHUNK_SIZE);
        } else {
            yRes = y / CHUNK_SIZE;
        }
        return new Point2(xRes, yRes);
    }

    public static Point2 worldToChunkCoordinates(Point2 worldCoordinates) {
        return worldToChunkCoordinates(worldCoordinates.x, worldCoordinates.y);
    }

    public static Point2 worldToLocalChunkCoordinates(int x, int y) {
        int xRes = 0;
        if (x < 0) {
            xRes = CHUNK_SIZE + (x % CHUNK_SIZE);
            xRes %= CHUNK_SIZE;
        } else {
            xRes = x % CHUNK_SIZE;
        }
        int yRes = 0;
        if (y < 0) {
            yRes = CHUNK_SIZE + (y % CHUNK_SIZE);
            yRes %= CHUNK_SIZE;
        } else {
            yRes = y % CHUNK_SIZE;
        }
        return new Point2(xRes, yRes);
    }

    public static Point2 worldToLocalChunkCoordinates(Point2 worldCoordinates) {
        return worldToLocalChunkCoordinates(worldCoordinates.x, worldCoordinates.y);
    }

    public static ThreadFactory createThreadFactory(final String identifier, final int priority) {
        return new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r, String.format("ISC-worker-%s", identifier));
                thread.setPriority(priority);
                return thread;
            }
        };
    }
}