package utils;

import java.awt.Graphics2D;
import java.awt.image.BufferedImageOp;
import java.awt.Composite;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.image.ImageObserver;
import java.awt.Image;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.FontFormatException;
import java.io.File;
import java.awt.Font;
import java.io.IOException;
import java.io.FileReader;
import java.io.Reader;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.awt.DisplayMode;
import java.awt.GraphicsDevice;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.awt.GraphicsConfiguration;

public class Utils {
    private static boolean RUNNING_FROM_JAR;
    private static Utils classLoaderReference;
    public static GraphicsConfiguration gc;
    
    static {
        Utils.classLoaderReference = null;
    }
    
    public static void init(final GraphicsConfiguration gc, final boolean jar) {
        Utils.gc = gc;
        Utils.RUNNING_FROM_JAR = jar;
    }
    
    public static String dateString() {
        return new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(new Date());
    }
    
    private static DisplayMode getBestDisplayMode(final GraphicsDevice device, final int xRes, final int yRes) {
        final DisplayMode[] BEST_DISPLAY_MODES = { new DisplayMode(xRes, yRes, 32, 0), new DisplayMode(xRes, yRes, 16, 0), new DisplayMode(xRes, yRes, 8, 0) };
        for (int x = 0; x < BEST_DISPLAY_MODES.length; ++x) {
            final DisplayMode[] modes = device.getDisplayModes();
            for (int i = 0; i < modes.length; ++i) {
                if (modes[i].getWidth() == BEST_DISPLAY_MODES[x].getWidth() && modes[i].getHeight() == BEST_DISPLAY_MODES[x].getHeight() && modes[i].getBitDepth() == BEST_DISPLAY_MODES[x].getBitDepth()) {
                    return BEST_DISPLAY_MODES[x];
                }
            }
        }
        return null;
    }
    
    public static void chooseBestDisplayMode(final GraphicsDevice device, final int xRes, final int yRes) {
        final DisplayMode best = getBestDisplayMode(device, xRes, yRes);
        if (best != null) {
            device.setDisplayMode(best);
        }
    }
    
    public static BufferedReader loadTextFile(final String fileName) throws IOException {
        if (Utils.RUNNING_FROM_JAR) {
            if (Utils.classLoaderReference == null) {
                Utils.classLoaderReference = new Utils();
            }
            return new BufferedReader(new InputStreamReader(Utils.classLoaderReference.getClass().getResourceAsStream("/" + fileName)));
        }
        return new BufferedReader(new FileReader(fileName));
    }
    
    public static Font loadFont(final String fileName) {
        try {
            if (Utils.RUNNING_FROM_JAR) {
                if (Utils.classLoaderReference == null) {
                    Utils.classLoaderReference = new Utils();
                }
                return Font.createFont(0, Utils.classLoaderReference.getClass().getResourceAsStream("/" + fileName));
            }
            return Font.createFont(0, new File(fileName));
        }
        catch (FontFormatException ffe) {
            ffe.printStackTrace();
        }
        catch (IOException ioe) {
            ioe.printStackTrace();
        }
        return null;
    }
    
    public static BufferedImage loadImg(final String fileName) {
        try {
            BufferedImage init;
            if (Utils.RUNNING_FROM_JAR) {
                if (Utils.classLoaderReference == null) {
                    Utils.classLoaderReference = new Utils();
                }
                init = ImageIO.read(Utils.classLoaderReference.getClass().getResource("/images/" + fileName));
            }
            else {
                init = ImageIO.read(new File("images/" + fileName));
            }
            final BufferedImage accelerated = Utils.gc.createCompatibleImage(init.getWidth(), init.getHeight(), 3);
            accelerated.getGraphics().drawImage(init, 0, 0, null);
            return accelerated;
        }
        catch (IOException ioe) {
            ioe.printStackTrace();
            return null;
        }
    }
    
    public static BufferedImage loadTransImg(final String fileName, final Color bgColor, final Color shadowColor) {
        try {
            BufferedImage init;
            if (Utils.RUNNING_FROM_JAR) {
                init = ImageIO.read(Utils.classLoaderReference.getClass().getResource("/images/" + fileName));
            }
            else {
                init = ImageIO.read(new File("images/" + fileName));
            }
            init = makeColorTransparent(init, bgColor, 0);
            init = makeColorTransparent(init, shadowColor, -1593835520);
            final BufferedImage accelerated = Utils.gc.createCompatibleImage(init.getWidth(), init.getHeight(), 3);
            accelerated.getGraphics().drawImage(init, 0, 0, null);
            return accelerated;
        }
        catch (IOException ioe) {
            ioe.printStackTrace();
            return null;
        }
    }
    
    public static BufferedImage makeColorTransparent(final BufferedImage image, final Color color, final int newColor) {
        final BufferedImage dimg = new BufferedImage(image.getWidth(), image.getHeight(), 2);
        final Graphics2D g = dimg.createGraphics();
        g.setComposite(AlphaComposite.Src);
        g.drawImage(image, null, 0, 0);
        g.dispose();
        for (int i = 0; i < dimg.getHeight(); ++i) {
            for (int j = 0; j < dimg.getWidth(); ++j) {
                if (dimg.getRGB(j, i) == color.getRGB()) {
                    dimg.setRGB(j, i, newColor);
                }
            }
        }
        return dimg;
    }
}