<!DOCTYPE html>
<style>
    body {
        background-color: #eee;
        text-align: center;
        padding-top: 20px;
    }
    
    #emblem {
        width: 128px;
        height: 128px;
        border: 1px solid black;
    }
    
    #scratch {
        width: 128px;
        height: 128px;
        border: 1px solid red;
        display: none;
    }
</style>
<canvas id="emblem"></canvas>
<canvas id="scratch"></canvas>
<script>
window.onload = function() {
    var baseUrl  = "https://api.guildwars2.com",
        guildId = "4BBB52AA-D768-4FC6-8EDE-C299F2822F0F",
        steps;
    
    function getJSON(url, cb) {
        var xhr = new XMLHttpRequest();
        
        xhr.onreadystatechange = function() {
            if(xhr.readyState !== 4) {
                return;
            }
            
            return cb(JSON.parse(xhr.responseText));
        };
        
        xhr.open("GET", baseUrl + url, true);
        xhr.send();
    }
    
    return getJSON("/v1/guild_details.json?guild_id=" + guildId, function(guild) {
        var data = {
                guild      : guild,
                colors     : null,
                background : null,
                foreground : null
            },
            colorIds = [
                guild.emblem.background_color_id,
                guild.emblem.foreground_primary_color_id,
                guild.emblem.foreground_secondary_color_id
            ];
        
        function checkPromise() {
            var missing = Object.keys(data).some(function(x) {
                    return !data[x];
                });
            
            if(!missing) {
                loadImages(data);
            }
        }
        
        // XXX: You really want to use promises here, but w/e this is super-vanilla.js.
        getJSON("/v2/colors?ids=" + colorIds.join(","), function(colors) {
            data.colors = colors.reduce(
                function(a, x) {
    	            // XXX: THESE ARE NOT THE RIGHT COLOR VALUES.
    	            // For how to obtain the color objects to the RGB
    	            // values used for colorization, refer to:
    	            //  * https://gist.github.com/codemasher/1cf2a5b0c323b0e67aef
    	            //  * https://forum-en.guildwars2.com/forum/community/api/How-To-Colors-API
    	            //  * https://forum-en.guildwars2.com/forum/community/api/API-Suggestion-Guilds

                    a[x.id] = {
                        r : x.cloth.rgb[0],
                        g : x.cloth.rgb[1],
                        b : x.cloth.rgb[2]
                    };
                    return a;
                },
                {}
            );
            checkPromise();
        });
        
        getJSON("/v2/emblem/backgrounds/" + guild.emblem.background_id, function(bg) {
            data.background = bg;
            checkPromise();
        });
        
        getJSON("/v2/emblem/foregrounds/" + guild.emblem.foreground_id, function(fg) {
            data.foreground = fg;
            checkPromise();
        });
    });
    
    function loadImages(data) {
        var allLayers = data.background.layers.concat(data.foreground.layers),
            loaded    = 0;
        
        data.images = {};
        
        // XXX: Promises would be nice here too.
        return allLayers.forEach(function(x) {
            var img = new Image();
            
            img.addEventListener("load", function() {
                data.images[x] = img;
                
                if(Object.keys(data.images).length === allLayers.length) {
                    renderEmblem(data);
                }
            });
            
            img.crossOrigin = "anonymous";
            img.src = x;
        });
    }
    
    function colorshift(ctx, img, rgb) {
        console.log(arguments);
        var data, bits, len;

        ctx.clearRect(0, 0, 128, 128);
        
        ctx.drawImage(
            img,
            0, 0, 128, 128,
            0, 0, 128, 128
        );
        
        data = ctx.getImageData(0, 0, 128, 128);
        bits = data.data;
        len = bits.length;
        
        for(var p = 0; p < len; p += 4) {
            bits[p + 0] = rgb.r;
            bits[p + 1] = rgb.g;
            bits[p + 2] = rgb.b;
            // Don't mess with the alpha.
        }
        
        ctx.putImageData(data, 0, 0);
    }
    
    function renderEmblem(data) {
        console.log(data);
        
        var $emblem    = document.querySelector("#emblem"),
            $scratch   = document.querySelector("#scratch"),
            ctxEmblem  = $emblem.getContext("2d"),
            ctxScratch = $scratch.getContext("2d"),
            background = data.background,
            foreground = data.foreground,
            emblem     = data.guild.emblem;
        
        $emblem.height = 128;
        $emblem.width = 128;
        $scratch.height = 128;
        $scratch.width = 128;
        
        function drawImage(image) {
            ctxEmblem.drawImage(
                typeof image === "string"
                    ? data.images[image]
                    : image,
                0, 0, 128, 128,
                0, 0, 128, 128
            );
        }
        
        function drawColored(image, color) {
            colorshift(
                ctxScratch,
                data.images[image],
                typeof color === "object"
                    ? color
                    : data.colors[color]
            );
            
            drawImage($scratch);
        }
        
        ctxEmblem.save();
            if(emblem.flags.indexOf("FlipBackgroundHorizontal") !== -1) {
                ctxEmblem.scale(-1, 1);
                ctxEmblem.translate(-128, 0);
            }
        
            if(emblem.flags.indexOf("FlipBackgroundVertical") !== -1) {
                ctxEmblem.scale(1, -1);
                ctxEmblem.translate(0, -128);
            }
        
            drawColored(background.layers[0], emblem.background_color_id);
        ctxEmblem.restore();
        
        ctxEmblem.save();
            if(emblem.flags.indexOf("FlipForegroundHorizontal") !== -1) {
                ctxEmblem.scale(-1, 1);
                ctxEmblem.translate(-128, 0);
            }
        
            if(emblem.flags.indexOf("FlipForegroundVertical") !== -1) {
                ctxEmblem.scale(1, -1);
                ctxEmblem.translate(0, -128);
            }
        
            // XXX: Not sure if this one is correct.
            drawColored(foreground.layers[0], {r:0, g:0, b:0});

            drawColored(foreground.layers[1], emblem.foreground_primary_color_id);
            drawColored(foreground.layers[2], emblem.foreground_secondary_color_id);
        ctxEmblem.restore();
    }
};
</script>
