package org.dynmap;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import javax.imageio.ImageIO;

import org.bukkit.entity.Player;
import org.bukkit.event.Event.Type;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.dynmap.MapType.ImageFormat;
import org.dynmap.debug.Debug;
import org.dynmap.utils.DynmapBufferedImage;
import org.dynmap.utils.FileLockManager;

/**
 * Listen for player logins, and process player faces by fetching skins *
 */
public class PlayerFaces {
    private DynmapPlugin plugin;
    private File facesdir;
    private File faces8x8dir;
    private File faces16x16dir;
    private File faces32x32dir;

    
    private class LoadPlayerImages implements Runnable {
        public String playername;
        public LoadPlayerImages(String playername) {
            this.playername = playername;
        }
        public void run() {
            BufferedImage img = null;
            try {
                URL url = new URL("http://s3.amazonaws.com/MinecraftSkins/" + playername + ".png");
                img = ImageIO.read(url);    /* Load skin for player */
            } catch (IOException iox) {
                Debug.debug("Error loading skin for '" + playername + "' - " + iox);
            }
            if(img == null) {
                try {
                    InputStream in = getClass().getResourceAsStream("/char.png");
                    img = ImageIO.read(in);    /* Load generic skin for player */
                    in.close();
                } catch (IOException iox) {
                    Debug.debug("Error loading default skin for '" + playername + "' - " + iox);
                }
            }
            if(img == null) {   /* No image to process?  Quit */
                return;
            }
            int[] faceaccessory = new int[64];  /* 8x8 of face accessory */
            /* Get buffered image for face at 8x8 */
            DynmapBufferedImage face8x8 = DynmapBufferedImage.allocateBufferedImage(8, 8);
            img.getRGB(8, 8, 8, 8, face8x8.argb_buf, 0, 8); /* Read face from image */
            img.getRGB(40, 8, 8, 8, faceaccessory, 0, 8); /* Read face accessory from image */
            /* Apply accessory to face: first element is transparency color so only ones not matching it */
            for(int i = 0; i < 64; i++) {
                if(faceaccessory[i] != faceaccessory[0]) 
                    face8x8.argb_buf[i] = faceaccessory[i];
            }
            /* Write 8x8 file */
            File img_8x8 = new File(faces8x8dir, playername + ".png");
            FileLockManager.getWriteLock(img_8x8);
            try {
                FileLockManager.imageIOWrite(face8x8.buf_img, ImageFormat.FORMAT_PNG, img_8x8);
            } catch (IOException iox) {
                Log.severe("Cannot write player icon " + img_8x8.getPath());
            }
            FileLockManager.releaseWriteLock(img_8x8);
            /* Make 16x16 version */
            DynmapBufferedImage face16x16 = DynmapBufferedImage.allocateBufferedImage(16, 16);
            for(int i = 0; i < 16; i++) {
                for(int j = 0; j < 16; j++) {
                    face16x16.argb_buf[i*16+j] = face8x8.argb_buf[(i/2)*8 + (j/2)];
                }
            }
            /* Write 16x16 file */
            File img_16x16 = new File(faces16x16dir, playername + ".png");
            FileLockManager.getWriteLock(img_16x16);
            try {
                FileLockManager.imageIOWrite(face16x16.buf_img, ImageFormat.FORMAT_PNG, img_16x16);
            } catch (IOException iox) {
                Log.severe("Cannot write player icon " + img_16x16.getPath());
            }
            FileLockManager.releaseWriteLock(img_16x16);
            DynmapBufferedImage.freeBufferedImage(face16x16);

            /* Make 32x32 version */
            DynmapBufferedImage face32x32 = DynmapBufferedImage.allocateBufferedImage(32, 32);
            for(int i = 0; i < 32; i++) {
                for(int j = 0; j < 32; j++) {
                    face32x32.argb_buf[i*32+j] = face8x8.argb_buf[(i/4)*8 + (j/4)];
                }
            }
            /* Write 32x32 file */
            File img_32x32 = new File(faces32x32dir, playername + ".png");
            FileLockManager.getWriteLock(img_32x32);
            try {
                FileLockManager.imageIOWrite(face32x32.buf_img, ImageFormat.FORMAT_PNG, img_32x32);
            } catch (IOException iox) {
                Log.severe("Cannot write player icon " + img_32x32.getPath());
            }
            FileLockManager.releaseWriteLock(img_32x32);
            DynmapBufferedImage.freeBufferedImage(face32x32);
            
            DynmapBufferedImage.freeBufferedImage(face8x8);
            /* TODO: signal update for player icon to client */
        }
    }
    private class LoginListener extends PlayerListener {
        @Override
        public void onPlayerLogin(PlayerLoginEvent event) {
            MapManager.scheduleDelayedJob(new LoadPlayerImages(event.getPlayer().getName()), 0);
        }
    }
    public PlayerFaces(DynmapPlugin plugin) {
        this.plugin = plugin;
        plugin.registerEvent(Type.PLAYER_LOGIN, new LoginListener());
        facesdir = new File(plugin.tilesDirectory, "faces");
        facesdir.mkdirs();  /* Make sure directory exists */
        faces8x8dir = new File(facesdir, "8x8");
        faces8x8dir.mkdirs();
        faces16x16dir = new File(facesdir, "16x16");
        faces16x16dir.mkdirs();
        faces32x32dir = new File(facesdir, "32x32");
        faces32x32dir.mkdirs();
    }

    
}

@@ -2102,24 +2102,156 @@
 mage(8, 8);%0A
+            int%5B%5D bgcolor = new int%5B1%5D;%0A            img.getRGB(0, 0, 1, 1, bgcolor, 0, 1);  /* Get BG color (for accessory face) */%0A
             
@@ -2609,29 +2609,23 @@
 y%5Bi%5D != 
-faceaccess
+bgcol
 or
-y
 %5B0%5D) %0A  
@@ -2682,16 +2682,120 @@
 ory%5Bi%5D;%0A
+                else if(face8x8.argb_buf%5Bi%5D == bgcolor%5B0%5D)%0A                    face8x8.argb_buf%5Bi%5D = 0;%0A
         

Fix accessory face mixing