text:
// TODO: clean this up. fewer globals

//var Growable = require('../growable');

// TODO: use object pool for vector arrays
var pool = require('../object-pool');
var timer = require('../timer');
var Coordinator;
var chunkCache;
var chunkSize = 2;
var voxelArraySize = chunkSize * chunkSize * chunkSize;
var tab = " ";
var debug = false;
var out = {};
var voxelsToTextures;
var textureOffsets;

// helps us load a cube with more than 1 texture
var addFace = function(basePosition, face, info) {
    var textureValue = info.textureValue;
    var start = info.start;
    var end = info.end;
    if (!textureValue && debug) {
        console.log('why are we here?');
    }
    var startX = basePosition[0] + start[0],
        startY = basePosition[1] + start[1],
        startZ = basePosition[2] + start[2],
        endX = basePosition[0] + end[0],
        endY = basePosition[1] + end[1],
        endZ = basePosition[2] + end[2];
    if (!(textureValue in out)) {
        // Start points Growable at 1/10 of chunk with single texture, 353808 floats
        // nah, 1/20 = 88452 floats

        // Going for no allocations
        out[textureValue] = {
            position: {
                offset: 0,
                data: pool.malloc('float32', 128000)
            },
            texcoord: {
                offset: 0,
                data: pool.malloc('float32', 128000)
            },
            normal: {
                offset: 0,
                data: pool.malloc('float32', 128000)
            }
        };
        /*
        out[textureValue] = {
            position: new Growable('float32', 256),
            texcoord: new Growable('float32', 256),
            normal: new Growable('float32', 256)
        };
        */
    }
    var points = out[textureValue].position;
    var texcoord = out[textureValue].texcoord;
    var normals = out[textureValue].normal;

    if (!(textureValue in textureOffsets)) {
        console.log(textureValue + 'not in ', textureOffsets);
    }

    var textureBottom = textureOffsets[textureValue][0];
    var textureTop = textureOffsets[textureValue][1];
    var textureRight = textureOffsets[textureValue][2];

    // COUNTER CLOCKWISE
    // no need to translate face, we already have
    switch (face) {
        // front and back are wrong
        case 'back':
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = startZ + 1;
            points.data[ points.offset++ ] = endX + 1;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = startZ + 1;
            points.data[ points.offset++ ] = endX + 1;
            points.data[ points.offset++ ] = endY + 1;
            points.data[ points.offset++ ] = startZ + 1;
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = startZ + 1;
            points.data[ points.offset++ ] = endX + 1;
            points.data[ points.offset++ ] = endY + 1;
            points.data[ points.offset++ ] = startZ + 1;
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = endY + 1;
            points.data[ points.offset++ ] = startZ + 1;

            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = textureBottom;
            texcoord.data[ texcoord.offset++ ] = 1.0; //endX - startX + 1;
            texcoord.data[ texcoord.offset++ ] = textureBottom;
            texcoord.data[ texcoord.offset++ ] = 1.0;
            texcoord.data[ texcoord.offset++ ] = textureTop; //endY - startY + 1 + textureOffset;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = textureTop;
            texcoord.data[ texcoord.offset++ ] = 1.0;
            texcoord.data[ texcoord.offset++ ] = textureTop;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = textureRight;

            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = 1.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = 1.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = 1.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = 1.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = 1.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = 1.0;
            break;

        case 'front':
            points.data[ points.offset++ ] = endX + 1;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = startZ;
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = startZ;
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = endY + 1;
            points.data[ points.offset++ ] = startZ;
            points.data[ points.offset++ ] = endX + 1;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = startZ;
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = endY + 1;
            points.data[ points.offset++ ] = startZ;
            points.data[ points.offset++ ] = endX + 1;
            points.data[ points.offset++ ] = endY + 1;
            points.data[ points.offset++ ] = startZ;

            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endX - startX + 1;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endX - startX + 1;
            texcoord.data[ texcoord.offset++ ] = endY - startY + 1;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endX - startX + 1;
            texcoord.data[ texcoord.offset++ ] = endY - startY + 1;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endY - startY + 1;

            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = -1.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = -1.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = -1.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = -1.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = -1.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = -1.0;
            break;

        case 'left':
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = startZ;
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = endZ + 1;
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = endY + 1;
            points.data[ points.offset++ ] = endZ + 1;
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = startZ;
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = endY + 1;
            points.data[ points.offset++ ] = endZ + 1;
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = startY + 1;
            points.data[ points.offset++ ] = startZ;

            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endZ - startZ + 1;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endZ - startZ + 1;
            texcoord.data[ texcoord.offset++ ] = endY - startY + 1;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endZ - startZ + 1;
            texcoord.data[ texcoord.offset++ ] = endY - startY + 1;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endY - startY + 1;

            normals.data[ normals.offset++ ] =  -1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = -1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = -1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = -1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = -1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = -1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] =  0.0;
            break;

        case 'right':
            points.data[ points.offset++ ] = startX + 1;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = endZ + 1;
            points.data[ points.offset++ ] = startX + 1;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = startZ;
            points.data[ points.offset++ ] = startX + 1;
            points.data[ points.offset++ ] = startY + 1;
            points.data[ points.offset++ ] = startZ;
            points.data[ points.offset++ ] = startX + 1;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = endZ + 1;
            points.data[ points.offset++ ] = startX + 1;
            points.data[ points.offset++ ] = startY + 1;
            points.data[ points.offset++ ] = startZ;
            points.data[ points.offset++ ] = startX + 1;
            points.data[ points.offset++ ] = endY + 1;
            points.data[ points.offset++ ] = endZ + 1;

            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endZ - startZ + 1;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endZ - startZ + 1;
            texcoord.data[ texcoord.offset++ ] = endY - startY + 1;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endZ - startZ + 1;
            texcoord.data[ texcoord.offset++ ] = endY - startY + 1;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endY - startY + 1;

            normals.data[ normals.offset++ ] = 1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = 1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = 1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = 1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = 1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = 1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] =  0.0;
            break;

        case 'top':
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = startY + 1;
            points.data[ points.offset++ ] = endZ + 1;
            points.data[ points.offset++ ] = endX + 1;
            points.data[ points.offset++ ] = startY + 1;
            points.data[ points.offset++ ] = endZ + 1;
            points.data[ points.offset++ ] = endX + 1;
            points.data[ points.offset++ ] = startY + 1;
            points.data[ points.offset++ ] = startZ;
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = startY + 1;
            points.data[ points.offset++ ] = endZ + 1;
            points.data[ points.offset++ ] = endX + 1;
            points.data[ points.offset++ ] = startY + 1;
            points.data[ points.offset++ ] = startZ;
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = startY + 1;
            points.data[ points.offset++ ] = startZ;

            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endX - startX + 1;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endX - startX + 1;
            texcoord.data[ texcoord.offset++ ] = endZ - startZ + 1;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endX - startX + 1;
            texcoord.data[ texcoord.offset++ ] = endZ - startZ + 1;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endZ - startZ + 1;

            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] =  1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] =  1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] =  1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] =  1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] =  1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] =  1.0;
            normals.data[ normals.offset++ ] =  0.0;
            break;

        case 'bottom':
            // bottom is
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = startZ;
            points.data[ points.offset++ ] = endX + 1;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = startZ;
            points.data[ points.offset++ ] = endX + 1;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = endZ + 1;
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = startZ;
            points.data[ points.offset++ ] = endX + 1;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = endZ + 1;
            points.data[ points.offset++ ] = startX;
            points.data[ points.offset++ ] = startY;
            points.data[ points.offset++ ] = endZ + 1;

            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endX - startX + 1;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endX - startX + 1;
            texcoord.data[ texcoord.offset++ ] = endZ - startZ + 1;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endX - startX + 1;
            texcoord.data[ texcoord.offset++ ] = endZ - startZ + 1;
            texcoord.data[ texcoord.offset++ ] = 0;
            texcoord.data[ texcoord.offset++ ] = endZ - startZ + 1;

            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = -1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = -1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = -1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = -1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = -1.0;
            normals.data[ normals.offset++ ] =  0.0;
            normals.data[ normals.offset++ ] = 0.0;
            normals.data[ normals.offset++ ] = -1.0;
            normals.data[ normals.offset++ ] =  0.0;
            break;
    }
};

var addFaces = function(basePosition, current) {
    for (var face in current) {
        if (current[face] != null) {
            addFace(basePosition, face, current[face]);
        }
    }
};

var resetFaces = function(current) {
    for (var face in current) {
        current[face] = null;
    }
};

var isFaceBlocked = function(basePosition, voxels, chunkSize, face, x, y, z, currentVoxelValue) {
    if (debug) {
        console.log('isFaceBlocked', chunkSize, face, x, y, z);
    }
    // Calculate coordinates of opposing block face
    switch (face) {
      case 'front':
        z--;
        break;

      case 'back':
        z++;
        break;

      case 'left':
        x--;
        break;

      case 'right':
        x++;
        break;

      case 'top':
        y++;
        break;

      case 'bottom':
        y--;
        break;
    }
    // Is this in another chunk? Use basePosition to calculate and check voxel from other chunk
    if (x < 0 || x >= chunkSize || y < 0 || y >= chunkSize || z < 0 || z >= chunkSize) {
        // Convert to world-relative position
        x += basePosition[0];
        y += basePosition[1];
        z += basePosition[2];
        // Get chunk those coordinates are within
        var opposingChunkID = Coordinator.coordinatesToChunkID(x, y, z);
        // Get index within that chunk
        var opposingIndex = Coordinator.coordinatesToVoxelIndex(x, y, z);
        //console.log(opposingChunkID, opposingIndex);
        if (opposingChunkID in chunkCache) {
            var opposingChunk = chunkCache[opposingChunkID];
            var opposingVoxelValue = opposingChunk.voxels[ opposingIndex ];
            return shouldSkipFace(currentVoxelValue, opposingVoxelValue);
        }

        return false;
    }
    var index = Coordinator.coordinatesToVoxelIndex(x, y, z);
    var opposingVoxelValue = voxels[index];

    return shouldSkipFace(currentVoxelValue, opposingVoxelValue);
};

var shouldSkipFace = function(currentVoxelValue, opposingVoxelValue) {
    if (opposingVoxelValue == 0) {
        return false;
    }
    /*
    We don't want to draw the transparent face if it's against an opaque one, but we do want to draw the opaque one
    Don't draw opaque face if opposite opaque face
    Don't draw transparent face if opposite transparent face
    */
    if (currentVoxelValue < 100) {
        if (opposingVoxelValue > 99) {
            return false;
        }
        return true;
    }
    // If we got here, the current face is transparent
    if (opposingVoxelValue > 0) {
        return true;
    }
    return false;
};

var faceIndex = function(face) {
    var map = {
        top: 0,
        front: 1,
        left: 2,
        back: 3,
        right: 4,
        bottom: 5
    };
    return map[face];
};

var calculate = function(basePosition, voxels) {
    var outside = chunkSize - 1;
    // Make position relative ... lower bound to 0 and adjust everything else
    for (var y = 0; y < chunkSize; y++) {
        // points to current start/end object for this face
        var adjacent = {
            front: null,
            back: null,
            top: null,
            bottom: null
        };
        var part = y * chunkSize;
        for (var z = 0; z < chunkSize; z++) {
            var index = part + (z * chunkSize * chunkSize);
            resetFaces(adjacent);
            for (var x = 0; x < chunkSize; x++) {
                var voxelTextureValue = voxels[index + x];
                if (voxelTextureValue == 0) {
                    addFaces(basePosition, adjacent);
                    resetFaces(adjacent);
                    continue;
                }
                if (!(voxelTextureValue in voxelsToTextures)) {
                    voxelTextureValue = 3;
                    console.log('falling back to 3');
                }
                // handle left and right faces separately
                // is left blocked, add it
                // is right blocked? add it
                // only loop through current pointer faces
                for (var face in adjacent) {
                    var isBlocked = false;
                    var textureValue = voxelsToTextures[voxelTextureValue].textures[faceIndex(face)];
                    isBlocked = isFaceBlocked(basePosition, voxels, chunkSize, face, x, y, z, textureValue);
                    if (debug) {
                        console.log('face: ' + face);
                    }
                    if (isBlocked) {
                        if (adjacent[face] != null) {
                            addFace(basePosition, face, adjacent[face]);
                            adjacent[face] = null;
                        }
                    } else {
                        // should we create a new face pointer?
                        if (adjacent[face] == null) {
                            if (debug) {
                                console.log('new pointer');
                            }
                            adjacent[face] = {
                                textureValue: textureValue,
                                start: [ x, y, z ],
                                end: [ x, y, z ]
                            };
                            if (debug) {
                                console.log(adjacent);
                            }
                        } else if (adjacent[face].textureValue == textureValue) {
                            if (debug) {
                                console.log('same texture');
                            }
                            // yes, update end position
                            adjacent[face].end[0] = x;
                            adjacent[face].end[1] = y;
                            adjacent[face].end[2] = z;
                        } else {
                            if (debug) {
                                console.log('else');
                            }
                            // no, close and create a new pointer for this face
                            addFace(basePosition, face, adjacent[face]);
                            adjacent[face] = {
                                textureValue: textureValue,
                                start: [ x, y, z ],
                                end: [ x, y, z ]
                            };
                        }
                    }
                }
            }
            // end X
            // Done with row, do we have any outstanding faces to add?
            addFaces(basePosition, adjacent);
            resetFaces(adjacent);
        } // end Z

        adjacent = {
            left: null,
            right: null
        };
        for (var x = 0; x < chunkSize; x++) {
            var index = part + x;
            resetFaces(adjacent);
            for (var z = 0; z < chunkSize; z++) {
                var voxelTextureValue = voxels[index + (z * chunkSize * chunkSize)];
                if (voxelTextureValue == 0) {
                    addFaces(basePosition, adjacent);
                    resetFaces(adjacent);
                    continue;
                }
                if (!(voxelTextureValue in voxelsToTextures)) {
                    voxelTextureValue = 3;
                    console.log('falling back to 3');
                }
                // handle left and right faces separately
                // is left blocked, add it
                // is right blocked? add it
                // only loop through current pointer faces
                for (var face in adjacent) {
                    var isBlocked = false;
                    var textureValue = voxelsToTextures[voxelTextureValue].textures[faceIndex(face)];
                    isBlocked = isFaceBlocked(basePosition, voxels, chunkSize, face, x, y, z, textureValue);
                    if (debug) {
                        console.log('face: ' + face, 'blocked:', isBlocked);
                    }
                    if (isBlocked > 0) {
                        if (adjacent[face] != null) {
                            addFace(basePosition, face, adjacent[face]);
                            adjacent[face] = null;
                        }
                    } else {
                        // should we create a new face pointer?
                        if (adjacent[face] == null) {
                            if (debug) {
                                console.log('new pointer');
                            }
                            adjacent[face] = {
                                textureValue: textureValue,
                                start: [ x, y, z ],
                                end: [ x, y, z ]
                            };
                            if (debug) {
                                console.log(adjacent);
                            }
                        } else if (adjacent[face].textureValue == textureValue) {
                            // yes, update end position
                            adjacent[face].end[0] = x;
                            adjacent[face].end[1] = y;
                            adjacent[face].end[2] = z;
                            if (debug) {
                                console.log('same texture', adjacent[face]);
                            }
                        } else {
                            if (debug) {
                                console.log('else');
                            }
                            // no, close and create a new pointer for this face
                            addFace(basePosition, face, adjacent[face]);
                            adjacent[face] = {
                                textureValue: textureValue,
                                start: [ x, y, z ],
                                end: [ x, y, z ]
                            };
                        }
                    }
                }
            }
            // end Z
            // Done with row, do we have any outstanding faces to add?
            addFaces(basePosition, adjacent);
            resetFaces(adjacent);
        } // end X
    } // end Y

};

if (!module) {
    var module = {};
}

var Meshing = module.exports = {
    config: function(cs, voxToTex, texOffsets, coordinatorHandle, cache) {
        chunkSize = cs;
        voxelArraySize = chunkSize * chunkSize * chunkSize;
        voxelsToTextures = voxToTex;
        textureOffsets = texOffsets;
        console.log(textureOffsets);
        Coordinator = coordinatorHandle;
        chunkCache = cache;
    },
    // position is chunk lower boundary
    mesh: function(position, voxels) {
        if (!voxels || voxels.length == 0) {
            console.log('Empty voxels');
            return null;
        }
        // Reset
        out = {};
        var start = Date.now();
        calculate(position, voxels);
        timer.log('mesher', Date.now() - start);
        return out;
    }
};


text:
namespace Nektar
{
    namespace LocalRegions
    {
        class Expansion2D;
        typedef boost::shared_ptr<Expansion2D> Expansion2DSharedPtr;
        typedef boost::weak_ptr<Expansion2D> Expansion2DWeakPtr;

        class Expansion1D;
        typedef boost::shared_ptr<Expansion1D> Expansion1DSharedPtr;
        typedef boost::weak_ptr<Expansion1D> Expansion1DWeakPtr;
        typedef std::vector< Expansion1DSharedPtr > Expansion1DVector;
        typedef std::vector< Expansion1DSharedPtr >::iterator Expansion1DVectorIter;

        class Expansion1D: virtual public Expansion, virtual public StdRegions::StdExpansion1D
        {
            public:
                LOCAL_REGIONS_EXPORT Expansion1D(SpatialDomains::Geometry1DSharedPtr pGeom) : Expansion(pGeom), StdExpansion1D()
                {
                    m_elementEdgeLeft = -1;
                    m_elementEdgeRight = -1;
                }

                LOCAL_REGIONS_EXPORT virtual ~Expansion1D() {}

                LOCAL_REGIONS_EXPORT void AddNormTraceInt(
                        const int dir,
                        Array<OneD, const NekDouble> &inarray,
                        Array<OneD,NekDouble> &outarray);

                inline Expansion2DSharedPtr GetLeftAdjacentElementExp() const;

                inline Expansion2DSharedPtr GetRightAdjacentElementExp() const;

                inline int GetLeftAdjacentElementEdge() const;

                inline int GetRightAdjacentElementEdge() const;

                inline void SetAdjacentElementExp(
                        int edge,
                        Expansion2DSharedPtr &e);

                void AddHDGHelmholtzTraceTerms(
                        const NekDouble tau,
                        const Array<OneD,const NekDouble> &inarray,
                              Array<OneD,NekDouble> &outarray);

                inline SpatialDomains::Geometry1DSharedPtr GetGeom1D() const;

            protected:
                virtual DNekMatSharedPtr v_GenMatrix(const StdRegions::StdMatrixKey &mkey);

                virtual void v_AddRobinMassMatrix(
                        const int vert,
                        const Array<OneD, const NekDouble > &primCoeffs,
                        DNekMatSharedPtr &inoutmat);

                virtual void v_AddRobinEdgeContribution(
                        const int vert,
                        const Array<OneD, const NekDouble > &primCoeffs,
                              Array<OneD, NekDouble> &coeffs);

            private:
                Expansion2DWeakPtr m_elementLeft;
                Expansion2DWeakPtr m_elementRight;
                int m_elementEdgeLeft;
                int m_elementEdgeRight;

        };

        inline Expansion2DSharedPtr Expansion1D::GetLeftAdjacentElementExp() const
        {
            ASSERTL1(m_elementLeft.lock().get(), "Left adjacent element not set.");
            return m_elementLeft.lock();
        }

        inline Expansion2DSharedPtr Expansion1D::GetRightAdjacentElementExp() const
        {
            ASSERTL1(m_elementLeft.lock().get(), "Right adjacent element not set.");
            return m_elementRight.lock();
        }

        inline int Expansion1D::GetLeftAdjacentElementEdge() const
        {
            return m_elementEdgeLeft;
        }

        inline int Expansion1D::GetRightAdjacentElementEdge() const
        {
            return m_elementEdgeRight;
        }

        inline void Expansion1D::SetAdjacentElementExp(int edge, Expansion2DSharedPtr &e)
        {
            if (m_elementLeft.lock().get())
            {
                ASSERTL1(!m_elementRight.lock().get(),
                         "Both adjacent elements already set.");
                m_elementRight = e;
                m_elementEdgeRight = edge;
            }
            else
            {
                m_elementLeft = e;
                m_elementEdgeLeft = edge;
            }
        }

        inline SpatialDomains::Geometry1DSharedPtr Expansion1D::GetGeom1D() const
        {
            return boost::dynamic_pointer_cast<SpatialDomains::Geometry1D>(m_geom);
        }
    } //end of namespace
} //end of namespace

#endif

redpajama_set_name: RedPajamaGithub


text:
var express = require('express');

var router = express.Router();

var wechatApiUtils = require('../utils/wechatApiUtils');

router.get('/getDeviceGroupList',function (req,res) {
    var deviceGroupList = wechatApiUtils.getDeviceGroupList();

    res.send(deviceGroupList);
});

module.exports = router;


text:
package org.apereo.cas.support.oauth.web.response.callback;

import org.apereo.cas.AbstractOAuth20Tests;
import org.apereo.cas.mock.MockTicketGrantingTicket;
import org.apereo.cas.services.RegisteredServiceTestUtils;
import org.apereo.cas.support.oauth.OAuth20Constants;
import org.apereo.cas.support.oauth.OAuth20GrantTypes;
import org.apereo.cas.support.oauth.OAuth20ResponseTypes;
import org.apereo.cas.support.oauth.web.response.accesstoken.ext.AccessTokenRequestContext;

import lombok.val;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.URIBuilder;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.view.RedirectView;

import java.util.AbstractMap;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.junit.jupiter.api.Assertions.*;

/**
 * This is {@link OAuth20TokenAuthorizationResponseBuilderTests}.
 *
 * @author David Albrecht
 * @since 6.1.3
 */
@Tag("OAuth")
public class OAuth20TokenAuthorizationResponseBuilderTests extends AbstractOAuth20Tests {
    private static final String STATE = "%123=";

    private static final String NONCE = "%123=";

    private static void verifyParam(final Map<String, List<String>> params, final String paramName, final String expectedParamValue) {
        assertTrue(params.containsKey(paramName), () -> "Expected " + paramName + "  param in redirect URL");
        assertEquals(1,
            params
                .get(paramName)
                .size(),
            () -> "Expected one value for " + paramName + " param");
        assertEquals(expectedParamValue,
            params
                .get(paramName)
                .get(0),
            () -> "Expected unchanged " + paramName + "  param");
    }

    private static Map<String, List<String>> splitQuery(final String fragment) {
        if (StringUtils.isBlank(fragment)) {
            return new HashMap<>(0);
        }
        return Arrays
            .stream(fragment.split("&"))
            .map(OAuth20TokenAuthorizationResponseBuilderTests::splitQueryParameter)
            .collect(Collectors.groupingBy(AbstractMap.SimpleImmutableEntry::getKey,
                LinkedHashMap::new, Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
    }

    private static AbstractMap.SimpleImmutableEntry<String, String> splitQueryParameter(final String it) {
        val idx = it.indexOf('=');
        val key = idx > 0 ? it.substring(0, idx) : it;
        val value = idx > 0 && it.length() > idx + 1 ? it.substring(idx + 1) : null;
        return new AbstractMap.SimpleImmutableEntry<>(key, value);
    }

    @Test
    public void verifyUnchangedStateAndNonceParameter() throws Exception {
        assertEquals(Ordered.LOWEST_PRECEDENCE, oauthAuthorizationCodeResponseBuilder.getOrder());

        val registeredService = getRegisteredService("example", CLIENT_SECRET, new LinkedHashSet<>());
        registeredService.setJwtAccessToken(true);
        servicesManager.save(registeredService);

        val service = RegisteredServiceTestUtils.getService("example");
        val attributes = new HashMap<String, List<Object>>();
        attributes.put(OAuth20Constants.STATE, Collections.singletonList(STATE));
        attributes.put(OAuth20Constants.NONCE, Collections.singletonList(NONCE));

        val holder = AccessTokenRequestContext
            .builder()
            .clientId(registeredService.getClientId())
            .service(service)
            .authentication(RegisteredServiceTestUtils.getAuthentication(RegisteredServiceTestUtils.getPrincipal(ID), attributes))
            .registeredService(registeredService)
            .grantType(OAuth20GrantTypes.NONE)
            .responseType(OAuth20ResponseTypes.TOKEN)
            .ticketGrantingTicket(new MockTicketGrantingTicket(ID))
            .generateRefreshToken(true)
            .redirectUri("https://oauth.example.org")
            .build();
        val modelAndView = oauthTokenResponseBuilder.build(holder);
        assertTrue(modelAndView.getView() instanceof RedirectView, "Expected RedirectView");
        assertTrue(modelAndView.getModel().isEmpty());

        val redirectUrl = ((RedirectView) modelAndView.getView()).getUrl();
        val params = splitQuery(new URIBuilder(redirectUrl).getFragment());

        verifyParam(params, OAuth20Constants.STATE, STATE);
        verifyParam(params, OAuth20Constants.NONCE, NONCE);
    }
}


text:
package com.xeiam.xchange.bleutrade;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

import com.xeiam.xchange.currency.CurrencyPair;

public final class BleutradeUtils {

  public static String toPairString(CurrencyPair currencyPair) {

    return currencyPair.base.getCurrencyCode().toUpperCase() + "_" + currencyPair.counter.getCurrencyCode().toUpperCase();
  }

  public static CurrencyPair toCurrencyPair(String pairString) {

    String[] currencies = pairString.split("_");
    return new CurrencyPair(currencies[0], currencies[1]);
  }

  public static Date toDate(String timeStamp) {

    try {

      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss'.'SSS");
      sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
      return sdf.parse(timeStamp);

    } catch (ParseException e) {

      try {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
        return sdf.parse(timeStamp);

      } catch (ParseException e1) {

        e1.printStackTrace();
        return new Date(0L);

      }
    }
  }
}


text:
#include "CCComExtensionData.h"
#include "editor-support/cocostudio/ActionTimeline/CCActionTimeline.h"

namespace cocostudio
{
    IMPLEMENT_CLASS_COMPONENT_INFO(ComExtensionData)

    const std::string ComExtensionData::COMPONENT_NAME = "ComExtensionData";

    ComExtensionData::ComExtensionData()
    : _customProperty("")
    , _timelineData(nullptr)
    {
        _name = COMPONENT_NAME;
    }

    ComExtensionData::~ComExtensionData()
    {
        CC_SAFE_RELEASE(_timelineData);
    }

    ComExtensionData* ComExtensionData::create()
    {
        ComExtensionData * ret = new (std::nothrow) ComExtensionData();
        if (ret && ret->init())
        {
            ret->autorelease();
        }
        else
        {
            CC_SAFE_DELETE(ret);
        }
        return ret;
    }

    bool ComExtensionData::init()
    {
        _timelineData = cocostudio::timeline::ActionTimelineData::create(0);
        CC_SAFE_RETAIN(_timelineData);

        return true;
    }

    void ComExtensionData::onEnter()
    {
    }

    void ComExtensionData::onExit()
    {
        onRemove();
    }

    void ComExtensionData::onAdd()
    {
    }

    void ComExtensionData::onRemove()
    {
    }

    void ComExtensionData::setActionTag(int actionTag)
    {
        _timelineData->setActionTag(actionTag);
    }

    const int ComExtensionData::getActionTag() const
    {
        return _timelineData->getActionTag();
    }

}


text:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections.Generic;
using System.Linq;
using EnvDTE80;
using Microsoft.VisualStudio.IntegrationTest.Utilities.Common;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.TableControl;
using Microsoft.VisualStudio.Shell.TableManager;

namespace Microsoft.VisualStudio.IntegrationTest.Utilities.InProcess
{
    internal class FindReferencesWindow_InProc : InProcComponent
    {
        public static FindReferencesWindow_InProc Create() => new FindReferencesWindow_InProc();

        public Reference[] GetContents(string windowCaption)
        {
            return InvokeOnUIThread(cancellationToken =>
            {
                // Find the tool window
                var toolWindow = ((DTE2)GetDTE()).ToolWindows.GetToolWindow(windowCaption);

                // Dig through to get the Find References control.
                var toolWindowType = toolWindow.GetType();
                var toolWindowControlField = toolWindowType.GetField("Control");
                var toolWindowControl = toolWindowControlField.GetValue(toolWindow);

                // Dig further to get the results table (as opposed to the toolbar).
                var tableControlAndCommandTargetType = toolWindowControl.GetType();
                var tableControlField = tableControlAndCommandTargetType.GetField("TableControl");
                var tableControl = (IWpfTableControl2)tableControlField.GetValue(toolWindowControl);

                // Remove all grouping
                var columnStates = tableControl.ColumnStates;
                var newColumnsStates = new List<ColumnState2>();
                foreach (ColumnState2 state in columnStates)
                {
                    var newState = new ColumnState2(
                        state.Name,
                        state.IsVisible,
                        state.Width,
                        state.SortPriority,
                        state.DescendingSort,
                        groupingPriority: 0);
                    newColumnsStates.Add(newState);
                }
                tableControl.SetColumnStates(newColumnsStates);

                // Force a refresh, if necessary. This doesn't re-run the Find References or
                // Find Implementations operation itself, it just forces the results to be
                // realized in the table.
                var forcedUpdateResult = ThreadHelper.JoinableTaskFactory.Run(async delegate
                {
                    return await tableControl.ForceUpdateAsync();
                });

                // Extract the basic text of the results.
                return forcedUpdateResult.AllEntries.Select(handle =>
                {
                    handle.TryGetValue(StandardTableKeyNames.DocumentName, out string filePath);
                    handle.TryGetValue(StandardTableKeyNames.Line, out int line);
                    handle.TryGetValue(StandardTableKeyNames.Column, out int column);
                    handle.TryGetValue(StandardTableKeyNames.Text, out string code);

                    var reference = new Reference
                    {
                        FilePath = filePath,
                        Line = line,
                        Column = column,
                        Code = code
                    };

                    return reference;
                }).ToArray();
            });
        }
    }
}


text:
{% extends "layout.html" %}

{% block page_title %}
  Start page example
{% endblock %}

{% block proposition_header %}

{% endblock %}

{% block header_class %}

{% endblock %}

{% block content %}

  {% include "../includes/phase_banner_alpha.html" %}

Home

Benefits

Carers and disability benefits

        {% if serviceName %} {{ serviceName }} {% endif %}

Use this service to:

do something

update your name, address or other details

you need to do this in order to do something else

Registering takes around 5 minutes.

        Start now

Before you start

You can also register by post.

The online service is also available in Welsh (Cymraeg).

You can't register for this service if you're in the UK illegally.

Subsection

Related link

Related link

More

{% endblock %}


text:
/*
 *
 * TINKER Source Code
 *
 *
 *  [2009] - [2013] Samuel Steven Truscott
 *  All Rights Reserved.
 */
/*
 * ##########################################
 * ##########################################
 * ##
 * ## The algorithms for the hashing - HASH_MAP_T##_hash - is taken
 * ## from the HashMap class of Java JDK 6 and is used here to get a
 * ## correct implementation together to generated suitable test-cases.
 * ##
 * ## Once these have been created the implementation should be changed
 * ## so it doesn't contain any JDK implementation details
 * ##
 * ##########################################
 * ##########################################
 */

#ifndef HASHED_MAP_H_
#define HASHED_MAP_H_

#include "tinker_api_types.h"
#include "tgt_types.h"
#include "memory/memory_manager.h"

/*
 * This abstract data type is used to model a hash-map.
 *
 * The KEY_T can be of most types but ideally should be discrete to
 * enable the contains_key function to work. The contains_value has
 * reduced in functionality because of this as it'll simply compare
 * the address of the values, not the actual value, because if it's
 * a complex type (struct) then the code will fall over.
 *
 * MAP_CAPACITY must be a power of 2 but this isn't enforced
 * by this code (yet). This is for the hashing algorithms
 * (technically it's the indexing part to ensure it's in range).
 *
 * First an abstract data type must be created or, if declared statically,
 * initialised using _create or _initialise.
 *
 * Then the user is free to put, get and remove entries.
 *
 * The details of the hash-map can be queried. The 'capacity' is the
 * total size of the table and the 'size' is the total number of
 * elements in the map.
 *
 * Once finished, if creating using _create, the _delete procedure
 * should be called to return all the user memory back to the heap.
 *
 * The hash-map is *NOT* synchronised and is therefore not thread safe.
 *
 */

#define DEFAULT_BUCKET_SIZE 16

typedef struct map_t map_t;
typedef struct map_it_t map_it_t;

typedef int32_t (map_create_hash)(const void * const data, const uint32_t size);

void map_initialise(
		map_t * const map,
		map_create_hash * const hashing_algorithm,
		mem_pool_info_t * const pool,
		uint32_t key_size);

map_t * map_create(
		map_create_hash * const hashing_algorithm,
		mem_pool_info_t * const pool,
		uint32_t key_size);

void map_delete(map_t * const map);
bool_t map_get(const map_t * const map, const void * key, void ** const value);
bool_t map_put(map_t * const map, const void * key, void * value);
bool_t map_remove(map_t * const map, const void * key);
uint32_t map_size(const map_t * const map);
uint32_t map_capacity(const map_t * const map);
bool_t map_contains_key(const map_t * const map, const void * key);

void map_it_initialise(map_it_t * const it, map_t * const map);
map_it_t * map_it_create(map_t * const map);
void map_it_delete(map_it_t * const it);
bool_t map_it_get(map_it_t * const it, void ** item);
bool_t map_it_next(map_it_t * const it, void ** item);
void map_it_reset(map_it_t * const it);

#endif /* HASHED_MAP_H_ */


text:
Question

Analysis

Code

Please in backup code here!


text:
*[Click here to see the Product Generator in action!](https://ternus.github.io/nsaproductgenerator/)*

Inspired by the leak of NSA's TAO product catalog. "I Can't Believe It's Not Classified" -- contains 0% top-secret verbiage.

If you're looking to modify the code, the word lists and (more or less) Mad Lib engine are all in nsa.js, which uses Handlebars.js to do templating.

Have fun!

-ternus
Jan '14


text:
// Generated by Apple Swift version 3.0.1 (swiftlang-800.0.58.6 clang-800.0.42.1)
#pragma clang diagnostic push

#if defined(__has_include) && __has_include(<swift/objc-prologue.h>)
# include <swift/objc-prologue.h>
#endif

#pragma clang diagnostic ignored "-Wauto-import"
#include <objc/NSObject.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

#if !defined(SWIFT_TYPEDEFS)
# define SWIFT_TYPEDEFS 1
# if defined(__has_include) && __has_include(<uchar.h>)
#  include <uchar.h>
# elif !defined(__cplusplus) || __cplusplus < 201103L
typedef uint_least16_t char16_t;
typedef uint_least32_t char32_t;
# endif
typedef float swift_float2  __attribute__((__ext_vector_type__(2)));
typedef float swift_float3  __attribute__((__ext_vector_type__(3)));
typedef float swift_float4  __attribute__((__ext_vector_type__(4)));
typedef double swift_double2  __attribute__((__ext_vector_type__(2)));
typedef double swift_double3  __attribute__((__ext_vector_type__(3)));
typedef double swift_double4  __attribute__((__ext_vector_type__(4)));
typedef int swift_int2  __attribute__((__ext_vector_type__(2)));
typedef int swift_int3  __attribute__((__ext_vector_type__(3)));
typedef int swift_int4  __attribute__((__ext_vector_type__(4)));
typedef unsigned int swift_uint2  __attribute__((__ext_vector_type__(2)));
typedef unsigned int swift_uint3  __attribute__((__ext_vector_type__(3)));
typedef unsigned int swift_uint4  __attribute__((__ext_vector_type__(4)));
#endif

#if !defined(SWIFT_PASTE)
# define SWIFT_PASTE_HELPER(x, y) x##y
# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y)
#endif
#if !defined(SWIFT_METATYPE)
# define SWIFT_METATYPE(X) Class
#endif
#if !defined(SWIFT_CLASS_PROPERTY)
# if __has_feature(objc_class_property)
#  define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__
# else
#  define SWIFT_CLASS_PROPERTY(...)
# endif
#endif

#if defined(__has_attribute) && __has_attribute(objc_runtime_name)
# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X)))
#else
# define SWIFT_RUNTIME_NAME(X)
#endif
#if defined(__has_attribute) && __has_attribute(swift_name)
# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X)))
#else
# define SWIFT_COMPILE_NAME(X)
#endif
#if defined(__has_attribute) && __has_attribute(objc_method_family)
# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X)))
#else
# define SWIFT_METHOD_FAMILY(X)
#endif
#if defined(__has_attribute) && __has_attribute(noescape)
# define SWIFT_NOESCAPE __attribute__((noescape))
#else
# define SWIFT_NOESCAPE
#endif
#if !defined(SWIFT_CLASS_EXTRA)
# define SWIFT_CLASS_EXTRA
#endif
#if !defined(SWIFT_PROTOCOL_EXTRA)
# define SWIFT_PROTOCOL_EXTRA
#endif
#if !defined(SWIFT_ENUM_EXTRA)
# define SWIFT_ENUM_EXTRA
#endif
#if !defined(SWIFT_CLASS)
# if defined(__has_attribute) && __has_attribute(objc_subclassing_restricted)
#  define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA
#  define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# else
#  define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
#  define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# endif
#endif

#if !defined(SWIFT_PROTOCOL)
# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
#endif

#if !defined(SWIFT_EXTENSION)
# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__)
#endif

#if !defined(OBJC_DESIGNATED_INITIALIZER)
# if defined(__has_attribute) && __has_attribute(objc_designated_initializer)
#  define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
# else
#  define OBJC_DESIGNATED_INITIALIZER
# endif
#endif
#if !defined(SWIFT_ENUM)
# define SWIFT_ENUM(_type, _name) enum _name : _type _name; enum SWIFT_ENUM_EXTRA _name : _type
# if defined(__has_feature) && __has_feature(generalized_swift_name)
#  define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_EXTRA _name : _type
# else
#  define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME) SWIFT_ENUM(_type, _name)
# endif
#endif
#if !defined(SWIFT_UNAVAILABLE)
# define SWIFT_UNAVAILABLE __attribute__((unavailable))
#endif
#if defined(__has_feature) && __has_feature(modules)
@import UIKit;
@import Foundation;
@import CoreGraphics;
@import ObjectiveC;
#endif

#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch"
#pragma clang diagnostic ignored "-Wduplicate-method-arg"
@class UIImage;
@class CALayer;
@class NSCoder;

/**
  \code
  AnimatedImageView
  \endcode is a subclass of \code
  UIImageView
  \endcode for displaying animated image.
*/
SWIFT_CLASS("_TtC14Kingfisher_iOS17AnimatedImageView")
@interface AnimatedImageView : UIImageView
/**
  Whether automatically play the animation when the view become visible. Default is true.
*/
@property (nonatomic) BOOL autoPlayAnimatedImage;
/**
  The size of the frame cache.
*/
@property (nonatomic) NSInteger framePreloadCount;
/**
  Specifies whether the GIF frames should be pre-scaled to save memory. Default is true.
*/
@property (nonatomic) BOOL needsPrescaling;
/**
  The animation timer's run loop mode. Default is \code
  NSRunLoopCommonModes
  \endcode. Set this property to \code
  NSDefaultRunLoopMode
  \endcode will make the animation pause during UIScrollView scrolling.
*/
@property (nonatomic) NSRunLoopMode _Nonnull runLoopMode;
@property (nonatomic, strong) UIImage * _Nullable image;
@property (nonatomic, readonly) BOOL isAnimating;
/**
  Starts the animation.
*/
- (void)startAnimating;
/**
  Stops the animation.
*/
- (void)stopAnimating;
- (void)displayLayer:(CALayer * _Nonnull)layer;
- (void)didMoveToWindow;
- (void)didMoveToSuperview;
- (BOOL)shouldPreloadAllGIF;
- (nonnull instancetype)initWithImage:(UIImage * _Nullable)image OBJC_DESIGNATED_INITIALIZER;
- (nonnull instancetype)initWithImage:(UIImage * _Nullable)image highlightedImage:(UIImage * _Nullable)highlightedImage OBJC_DESIGNATED_INITIALIZER;
- (nonnull instancetype)initWithFrame:(CGRect)frame OBJC_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER;
@end

@class NSURLSessionConfiguration;
@class OS_dispatch_queue;

/**
  \code
  ImageDownloader
  \endcode represents a downloading manager for requesting the image with a URL from server.
*/
SWIFT_CLASS("_TtC14Kingfisher_iOS15ImageDownloader")
@interface ImageDownloader : NSObject
/**
  The duration before the download is timeout. Default is 15 seconds.
*/
@property (nonatomic) NSTimeInterval downloadTimeout;
/**
  A set of trusted hosts when receiving server trust challenges. A challenge with host name contained in this set will be ignored.
  You can use this set to specify the self-signed site. It only will be used if you don't specify the \code
  authenticationChallengeResponder
  \endcode.
  If \code
  authenticationChallengeResponder
  \endcode is set, this property will be ignored and the implemention of \code
  authenticationChallengeResponder
  \endcode will be used instead.
*/
@property (nonatomic, copy) NSSet<NSString *> * _Nullable trustedHosts;
/**
  Use this to set supply a configuration for the downloader. By default, NSURLSessionConfiguration.ephemeralSessionConfiguration() will be used.
  You could change the configuration before a downloaing task starts. A configuration without persistent storage for caches is requsted for downloader working correctly.
*/
@property (nonatomic, strong) NSURLSessionConfiguration * _Nonnull sessionConfiguration;
/**
  Whether the download requests should use pipeling or not. Default is false.
*/
@property (nonatomic) BOOL requestsUsePipeling;
@property (nonatomic, readonly, strong) OS_dispatch_queue * _Nonnull barrierQueue;
@property (nonatomic, readonly, strong) OS_dispatch_queue * _Nonnull processQueue;
/**
  The default downloader.
*/
SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly, strong, getter=default) ImageDownloader * _Nonnull default_;)
+ (ImageDownloader * _Nonnull)default;
/**
  Init a downloader with name.
  \param name The name for the downloader. It should not be empty.

  returns:
  The downloader object.
*/
- (nonnull instancetype)initWithName:(NSString * _Nonnull)name OBJC_DESIGNATED_INITIALIZER;
- (nonnull instancetype)init SWIFT_UNAVAILABLE;
@end

@interface ImageDownloader (SWIFT_EXTENSION(Kingfisher_iOS))
@end

@interface ImageDownloader (SWIFT_EXTENSION(Kingfisher_iOS))
- (void)cleanFor:(NSURL * _Nonnull)url;
@end

@class NSURLSession;
@class NSURLSessionDataTask;
@class NSURLResponse;
@class NSURLSessionTask;
@class NSURLAuthenticationChallenge;
@class NSURLCredential;

SWIFT_CLASS("_TtC14Kingfisher_iOS29ImageDownloaderSessionHandler")
@interface ImageDownloaderSessionHandler : NSObject <NSURLSessionDataDelegate>
@property (nonatomic, strong) ImageDownloader * _Nullable downloadHolder;
- (void)URLSession:(NSURLSession * _Nonnull)session dataTask:(NSURLSessionDataTask * _Nonnull)dataTask didReceiveResponse:(NSURLResponse * _Nonnull)response completionHandler:(void (^ _Nonnull)(NSURLSessionResponseDisposition))completionHandler;
- (void)URLSession:(NSURLSession * _Nonnull)session dataTask:(NSURLSessionDataTask * _Nonnull)dataTask didReceiveData:(NSData * _Nonnull)data;
- (void)URLSession:(NSURLSession * _Nonnull)session task:(NSURLSessionTask * _Nonnull)task didCompleteWithError:(NSError * _Nullable)error;
/**
  This method is exposed since the compiler requests. Do not call it.
*/
- (void)URLSession:(NSURLSession * _Nonnull)session didReceiveChallenge:(NSURLAuthenticationChallenge * _Nonnull)challenge completionHandler:(void (^ _Nonnull)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler;
- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end

@interface NSMutableData (SWIFT_EXTENSION(Kingfisher_iOS))
/**
  Convenient way to append bytes
*/
- (void)appendBytes:(NSArray<NSNumber *> * _Nonnull)arrayOfBytes;
@end

@interface UIApplication (SWIFT_EXTENSION(Kingfisher_iOS))
@end

@interface UIButton (SWIFT_EXTENSION(Kingfisher_iOS))
@end

@interface UIButton (SWIFT_EXTENSION(Kingfisher_iOS))
/**
  Cancel the image download task bounded to the image view if it is running.
  Nothing will happen if the downloading has already finished.
*/
- (void)kf_cancelImageDownloadTask;
/**
  Cancel the background image download task bounded to the image view if it is running.
  Nothing will happen if the downloading has already finished.
*/
- (void)kf_cancelBackgroundImageDownloadTask;
/**
  Get the image URL binded to this button for a specified state.
  \param state The state that uses the specified image.

  returns:
  Current URL for image.
*/
- (NSURL * _Nullable)kf_webURLFor:(UIControlState)state;
/**
  Get the background image URL binded to this button for a specified state.
  \param state The state that uses the specified background image.

  returns:
  Current URL for background image.
*/
- (NSURL * _Nullable)kf_backgroundWebURLFor:(UIControlState)state;
@end

@interface UIColor (SWIFT_EXTENSION(Kingfisher_iOS))
@end

@interface UIImage (SWIFT_EXTENSION(Kingfisher_iOS))
@end

@interface UIImage (SWIFT_EXTENSION(Kingfisher_iOS))
@end

@interface UIImage (SWIFT_EXTENSION(Kingfisher_iOS))
/**
  Normalize the image. This method does nothing in OS X.

  returns:
  The image itself.
*/
- (UIImage * _Nonnull)kf_normalized;
/**
  Create a round corner image based on \code
  self
  \endcode.
  note:
  This method only works for CG-based image.
  \param radius The round corner radius of creating image.

  \param size The target size of creating image.

  \param scale The image scale of creating image.

  returns:
  An image with round corner of \code
  self
  \endcode.
*/
- (UIImage * _Nonnull)kf_imageWithRoundRadius:(CGFloat)radius fit:(CGSize)size scale:(CGFloat)scale;
/**
  Resize \code
  self
  \endcode to an image of new size.
  note:
  This method only works for CG-based image.
  \param size The target size.

  returns:
  An image with new size.
*/
- (UIImage * _Nonnull)kf_resizeTo:(CGSize)size;
/**
  Create an image with blur effect based on \code
  self
  \endcode.
  note:
  This method only works for CG-based image.
  \param radius The blur radius should be used when creating blue.

  returns:
  An image with blur effect applied.
*/
- (UIImage * _Nonnull)kf_blurredWithRadius:(CGFloat)radius;
/**
  Create an image from \code
  self
  \endcode with a color overlay layer.
  note:
  This method only works for CG-based image.
  \param color The color should be use to overlay.

  \param fraction Fraction of input color. From 0.0 to 1.0. 0.0 means solid color, 1.0 means transparent overlay.

  returns:
  An image with a color overlay applied.
*/
- (UIImage * _Nonnull)kf_overlayingWith:(UIColor * _Nonnull)color fraction:(CGFloat)fraction;
/**
  Create an image from \code
  self
  \endcode with a color tint.
  \param color The color should be used to tint \code
  self
  \endcode

  returns:
  An image with a color tint applied.
*/
- (UIImage * _Nonnull)kf_tintedWith:(UIColor * _Nonnull)color;
/**
  Create an image from \code
  self
  \endcode with color control.
  \param brightness Brightness changing to image.

  \param contrast Contrast changing to image.

  \param saturation Saturation changing to image.

  \param inputEV InputEV changing to image.

  returns:
  An image with color control applied.
*/
- (UIImage * _Nonnull)kf_adjustedWithBrightness:(CGFloat)brightness contrast:(CGFloat)contrast saturation:(CGFloat)saturation inputEV:(CGFloat)inputEV;
@end

@interface UIImageView (SWIFT_EXTENSION(Kingfisher_iOS))
@end

@interface UIImageView (SWIFT_EXTENSION(Kingfisher_iOS))
/**
  Cancel the image download task bounded to the image view if it is running.
  Nothing will happen if the downloading has already finished.
*/
- (void)kf_cancelDownloadTask;
/**
  Get the image URL binded to this image view.
*/
@property (nonatomic, readonly, copy) NSURL * _Nullable kf_webURL;
- (BOOL)shouldPreloadAllGIF;
@end

#pragma clang diagnostic pop


text:
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using Monitor.Tests.Helpers;
using Microsoft.Azure.Management.Monitor;
using Microsoft.Azure.Management.Monitor.Models;
using Xunit;
using Microsoft.Rest.Azure;

namespace Monitor.Tests.BasicTests
{
    public class ActionGroupsTests : TestBase
    {
        [Fact]
        [Trait("Category", "Mock")]
        public void CreateTestNotificationAtActionGroupLevelTest()
        {
            var expectedResponse = new HttpResponseMessage(HttpStatusCode.Accepted)
            {
                Content = new StringContent(@""),
            };

            expectedResponse.Headers.Location = new Uri("https://test.test");

            var handler = new RecordedDelegatingHandler(expectedResponse) { SubsequentStatusCodeToReturn = HttpStatusCode.OK };
            var insightsClient = GetMonitorManagementClient(handler);

            NotificationRequestBody request = GetNotificationRequestBody();
            var result = insightsClient.ActionGroups.CreateNotificationsAtActionGroupResourceLevel("Test-Rg", "test-Ag", request);

            Assert.NotNull(result);
        }

        [Fact]
        [Trait("Category", "Mock")]
        public void CreateTestNotificationAtResourceGroupLevelTest()
        {
            var expectedResponse = new HttpResponseMessage(HttpStatusCode.Accepted)
            {
                Content = new StringContent(@""),
            };

            expectedResponse.Headers.Location = new Uri("https://test.test");

            var handler = new RecordedDelegatingHandler(expectedResponse) { SubsequentStatusCodeToReturn = HttpStatusCode.OK };
            var insightsClient = GetMonitorManagementClient(handler);

            NotificationRequestBody request = GetNotificationRequestBody();
            var result = insightsClient.ActionGroups.CreateNotificationsAtResourceGroupLevel("Test-Rg", request);

            Assert.NotNull(result);
        }

        [Fact]
        [Trait("Category", "Mock")]
        public void GetTestNotificationStatusAtActionGroupLevelTest()
        {
            TestNotificationDetailsResponse expectedActionGroup = GetTestNotificationStatusResponseBody();

            var handler = new RecordedDelegatingHandler();
            var insightsClient = GetMonitorManagementClient(handler);
            var serializedObject = Microsoft.Rest.Serialization.SafeJsonConvert.SerializeObject(expectedActionGroup, insightsClient.SerializationSettings);
            var expectedResponse = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent(serializedObject)
            };

            handler = new RecordedDelegatingHandler(expectedResponse);
            insightsClient = GetMonitorManagementClient(handler);

            TestNotificationDetailsResponse statusResponse = insightsClient.ActionGroups.GetTestNotificationsAtActionGroupResourceLevel("Rg-Test", "Ag-Test", "11000340935222");

            Assert.Equal(statusResponse.Context.ContextType, expectedActionGroup.Context.ContextType);
            Assert.Equal(statusResponse.Context.NotificationSource, expectedActionGroup.Context.NotificationSource);
            Assert.Equal(statusResponse.CreatedTime, expectedActionGroup.CreatedTime);
            Assert.Equal(statusResponse.CompletedTime, expectedActionGroup.CompletedTime);
            Assert.Equal(statusResponse.State, expectedActionGroup.State);

            for (int i = 0; i < statusResponse.ActionDetails.Count; i++)
            {
                Assert.Equal(statusResponse.ActionDetails[i].MechanismType, expectedActionGroup.ActionDetails[i].MechanismType);
                Assert.Equal(statusResponse.ActionDetails[i].Name, expectedActionGroup.ActionDetails[i].Name);
                Assert.Equal(statusResponse.ActionDetails[i].SendTime, expectedActionGroup.ActionDetails[i].SendTime);
                Assert.Equal(statusResponse.ActionDetails[i].Status, expectedActionGroup.ActionDetails[i].Status);
                Assert.Equal(statusResponse.ActionDetails[i].SubState, expectedActionGroup.ActionDetails[i].SubState);
                Assert.Equal(statusResponse.ActionDetails[i].Detail, expectedActionGroup.ActionDetails[i].Detail);
            }
        }

        [Fact]
        [Trait("Category", "Mock")]
        public void GetTestNotificationStatusTest()
        {
            TestNotificationDetailsResponse expectedActionGroup = GetTestNotificationStatusResponseBody();

            var handler = new RecordedDelegatingHandler();
            var insightsClient = GetMonitorManagementClient(handler);
            var serializedObject = Microsoft.Rest.Serialization.SafeJsonConvert.SerializeObject(expectedActionGroup, insightsClient.SerializationSettings);
            var expectedResponse = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent(serializedObject)
            };

            handler = new RecordedDelegatingHandler(expectedResponse);
            insightsClient = GetMonitorManagementClient(handler);

            TestNotificationDetailsResponse statusResponse = insightsClient.ActionGroups.GetTestNotificationsAsync("11000340935777").Result;

            Assert.Equal(statusResponse.Context.ContextType, expectedActionGroup.Context.ContextType);
            Assert.Equal(statusResponse.Context.NotificationSource, expectedActionGroup.Context.NotificationSource);
            Assert.Equal(statusResponse.CreatedTime, expectedActionGroup.CreatedTime);
            Assert.Equal(statusResponse.CompletedTime, expectedActionGroup.CompletedTime);
            Assert.Equal(statusResponse.State, expectedActionGroup.State);

            for (int i = 0; i < statusResponse.ActionDetails.Count; i++)
            {
                Assert.Equal(statusResponse.ActionDetails[i].MechanismType, expectedActionGroup.ActionDetails[i].MechanismType);
                Assert.Equal(statusResponse.ActionDetails[i].Name, expectedActionGroup.ActionDetails[i].Name);
                Assert.Equal(statusResponse.ActionDetails[i].SendTime, expectedActionGroup.ActionDetails[i].SendTime);
                Assert.Equal(statusResponse.ActionDetails[i].Status, expectedActionGroup.ActionDetails[i].Status);
                Assert.Equal(statusResponse.ActionDetails[i].SubState, expectedActionGroup.ActionDetails[i].SubState);
                Assert.Equal(statusResponse.ActionDetails[i].Detail, expectedActionGroup.ActionDetails[i].Detail);
            }
        }

        [Fact]
        [Trait("Category", "Mock")]
        public void CreateOrUpdateActionGroupTest()
        {
            ActionGroupResource expectedParameters = GetCreateOrUpdateActionGroupParameter();

            var handler = new RecordedDelegatingHandler();
            var insightsClient = GetMonitorManagementClient(handler);
            var serializedObject = Microsoft.Rest.Serialization.SafeJsonConvert.SerializeObject(expectedParameters, insightsClient.SerializationSettings);
            serializedObject = serializedObject.Replace("{", "{\"name\":\"" + expectedParameters.Name + "\",\"id\":\"" + expectedParameters.Id + "\",");
            var expectedResponse = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent(serializedObject)
            };

            handler = new RecordedDelegatingHandler(expectedResponse);
            insightsClient = GetMonitorManagementClient(handler);

            var result = insightsClient.ActionGroups.CreateOrUpdate(resourceGroupName: "rg1", actionGroupName: expectedParameters.Name, actionGroup: expectedParameters);

            AreEqual(expectedParameters, result);
        }

        [Fact]
        [Trait("Category", "Mock")]
        public void GetActionGroupTest()
        {
            var expectedActionGroup = GetCreateOrUpdateActionGroupParameter(name: "name4");

            var handler = new RecordedDelegatingHandler();
            var insightsClient = GetMonitorManagementClient(handler);
            var serializedObject = Microsoft.Rest.Serialization.SafeJsonConvert.SerializeObject(expectedActionGroup, insightsClient.SerializationSettings);
            serializedObject = serializedObject.Replace("{", "{\"name\":\"" + expectedActionGroup.Name + "\",\"id\":\"" + expectedActionGroup.Id + "\",");
            var expectedResponse = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent(serializedObject)
            };

            handler = new RecordedDelegatingHandler(expectedResponse);
            insightsClient = GetMonitorManagementClient(handler);

            var actionGroup = insightsClient.ActionGroups.Get(
                resourceGroupName: "rg1",
                actionGroupName: "name4");

            AreEqual(expectedActionGroup, actionGroup);
        }

        [Fact]
        [Trait("Category", "Mock")]
        public void ListActionGroupsBySusbscriptionTest()
        {
            List<ActionGroupResource> expectedParameters = GetActionGroups();

            var handler = new RecordedDelegatingHandler();
            var insightsClient = GetMonitorManagementClient(handler);
            var serializedObject = Microsoft.Rest.Serialization.SafeJsonConvert.SerializeObject(expectedParameters, insightsClient.SerializationSettings);
            serializedObject = serializedObject.Replace("{", "{\"name\":\"" + expectedParameters[0].Name + "\",\"id\":\"" + expectedParameters[0].Id + "\",");
            var expectedResponse = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent(string.Concat("{ \"value\":", serializedObject, "}"))
            };

            handler = new RecordedDelegatingHandler(expectedResponse);
            insightsClient = GetMonitorManagementClient(handler);

            var actualGroups = insightsClient.ActionGroups.ListBySubscriptionId();

            AreEqual(expectedParameters.ToList(), actualGroups.ToList());
        }

        [Fact]
        [Trait("Category", "Mock")]
        public void ListActionGroupsByResourceGroupTest()
        {
            List<ActionGroupResource> expectedParameters = GetActionGroups();

            var handler = new RecordedDelegatingHandler();
            var insightsClient = GetMonitorManagementClient(handler);
            var serializedObject = Microsoft.Rest.Serialization.SafeJsonConvert.SerializeObject(expectedParameters, insightsClient.SerializationSettings);
            serializedObject = serializedObject.Replace("{", "{\"name\":\"" + expectedParameters[0].Name + "\",\"id\":\"" + expectedParameters[0].Id + "\",");
            var expectedResponse = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent(string.Concat("{ \"value\":", serializedObject, "}"))
            };

            handler = new RecordedDelegatingHandler(expectedResponse);
            insightsClient = GetMonitorManagementClient(handler);

            var actualGroups = insightsClient.ActionGroups.ListByResourceGroup(resourceGroupName: "rg1");

            AreEqual(expectedParameters.ToList(), actualGroups.ToList());
        }

        [Fact]
        [Trait("Category", "Mock")]
        public void UpdateActionGroupTest()
        {
            ActionGroupResource expectedParameters = GetCreateOrUpdateActionGroupParameter();

            var handler = new RecordedDelegatingHandler();
            var insightsClient = GetMonitorManagementClient(handler);
            var serializedObject = Microsoft.Rest.Serialization.SafeJsonConvert.SerializeObject(expectedParameters, insightsClient.SerializationSettings);
            serializedObject = serializedObject.Replace("{", "{\"name\":\"" + expectedParameters.Name + "\",\"id\":\"" + expectedParameters.Id + "\",");
            var expectedResponse = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent(serializedObject)
            };

            handler = new RecordedDelegatingHandler(expectedResponse);
            insightsClient = GetMonitorManagementClient(handler);

            ActionGroupPatchBody bodyParameter = new ActionGroupPatchBody
            {
                Enabled = true,
                Tags = null
            };

            var result = insightsClient.ActionGroups.Update(
                resourceGroupName: "rg1",
                actionGroupName: expectedParameters.Name,
                actionGroupPatch: bodyParameter);

            AreEqual(expectedParameters, result);
        }

        [Fact]
        [Trait("Category", "Mock")]
        public void DeleteActionGroupTest()
        {
            var handler = new RecordedDelegatingHandler();
            var monitorManagementClient = GetMonitorManagementClient(handler);
            var expectedResponse = new HttpResponseMessage(HttpStatusCode.OK);

            handler = new RecordedDelegatingHandler(expectedResponse);
            monitorManagementClient = GetMonitorManagementClient(handler);

            AzureOperationResponse response = monitorManagementClient.ActionGroups.DeleteWithHttpMessagesAsync(
                resourceGroupName: "rg1",
                actionGroupName: "name1").Result;

            Assert.Equal(HttpStatusCode.OK, response.Response.StatusCode);
        }

        [Fact]
        [Trait("Category", "Mock")]
        public void EnableActionGroupTest()
        {
            var handler = new RecordedDelegatingHandler();
            var monitorManagementClient = GetMonitorManagementClient(handler);
            var expectedResponse = new HttpResponseMessage(HttpStatusCode.OK);

            handler = new RecordedDelegatingHandler(expectedResponse);
            monitorManagementClient = GetMonitorManagementClient(handler);

            AzureOperationResponse response = monitorManagementClient.ActionGroups.EnableReceiverWithHttpMessagesAsync(
                resourceGroupName: "rg1",
                actionGroupName: "name1",
                receiverName: "receiverName1").Result;

            Assert.Equal(HttpStatusCode.OK, response.Response.StatusCode);
        }

        private static List<ActionGroupResource> GetActionGroups()
        {
            return new List<ActionGroupResource>
            {
                GetCreateOrUpdateActionGroupParameter(),
                GetCreateOrUpdateActionGroupParameter(),
                GetCreateOrUpdateActionGroupParameter()
            };
        }

        private static void AreEqual(ActionGroupResource exp, ActionGroupResource act)
        {
            if (exp != null)
            {
                Assert.Equal(exp.Id, act.Id);
                Assert.Equal(exp.Name, act.Name);
                Assert.Equal(exp.Location, act.Location);
                Assert.Equal(exp.GroupShortName, act.GroupShortName);
                Assert.Equal(exp.Enabled, act.Enabled);
                Utilities.AreEqual(exp.Tags, act.Tags);
                AreEqual(exp.EmailReceivers, act.EmailReceivers);
                AreEqual(exp.SmsReceivers, act.SmsReceivers);
                AreEqual(exp.WebhookReceivers, act.WebhookReceivers);
                AreEqual(exp.ItsmReceivers, act.ItsmReceivers);
                AreEqual(exp.AzureAppPushReceivers, act.AzureAppPushReceivers);
                AreEqual(exp.AutomationRunbookReceivers, act.AutomationRunbookReceivers);
                AreEqual(exp.EventHubReceivers, exp.EventHubReceivers);
            }
        }

        private static void AreEqual(IList<EmailReceiver> exp, IList<EmailReceiver> act)
        {
            if (exp != null)
            {
                for (int i = 0; i < exp.Count; i++)
                {
                    AreEqual(exp[i], act[i]);
                }
            }
        }

        private static void AreEqual(IList<ActionGroupResource> exp, IList<ActionGroupResource> act)
        {
            if (exp != null)
            {
                for (int i = 0; i < exp.Count; i++)
                {
                    AreEqual(exp[i], act[i]);
                }
            }
        }

        private static void AreEqual(IList<SmsReceiver> exp, IList<SmsReceiver> act)
        {
            if (exp != null)
            {
                for (int i = 0; i < exp.Count; i++)
                {
                    AreEqual(exp[i], act[i]);
                }
            }
        }

        private static void AreEqual(IList<WebhookReceiver> exp, IList<WebhookReceiver> act)
        {
            if (exp != null)
            {
                for (int i = 0; i < exp.Count; i++)
                {
                    AreEqual(exp[i], act[i]);
                }
            }
        }

        private static void AreEqual(IList<AzureAppPushReceiver> exp, IList<AzureAppPushReceiver> act)
        {
            if (exp != null)
            {
                for (int i = 0; i < exp.Count; i++)
                {
                    AreEqual(exp[i], act[i]);
                }
            }
        }

        private static void AreEqual(IList<ItsmReceiver> exp, IList<ItsmReceiver> act)
        {
            if (exp != null)
            {
                for (int i = 0; i < exp.Count; i++)
                {
                    AreEqual(exp[i], act[i]);
                }
            }
        }

        private static void AreEqual(IList<AutomationRunbookReceiver> exp, IList<AutomationRunbookReceiver> act)
        {
            if (exp != null)
            {
                for (int i = 0; i < exp.Count; i++)
                {
                    AreEqual(exp[i], act[i]);
                }
            }
        }

        private static void AreEqual(IList<EventHubReceiver> exp, IList<EventHubReceiver> act)
        {
            if (exp != null)
            {
                for (int i = 0; i < exp.Count; i++)
                {
                    AreEqual(exp[i], act[i]);
                }
            }
        }

        private static void AreEqual(EmailReceiver exp, EmailReceiver act)
        {
            if (exp != null)
            {
                Assert.Equal(exp.EmailAddress, act.EmailAddress);
                Assert.Equal(exp.Name, act.Name);
                Assert.Equal(exp.Status, act.Status);
            }
        }

        private static void AreEqual(SmsReceiver exp, SmsReceiver act)
        {
            if (exp != null)
            {
                Assert.Equal(exp.PhoneNumber, act.PhoneNumber);
                Assert.Equal(exp.Name, act.Name);
                Assert.Equal(exp.Status, act.Status);
            }
        }

        private static void AreEqual(WebhookReceiver exp, WebhookReceiver act)
        {
            if (exp != null)
            {
                Assert.Equal(exp.ServiceUri, act.ServiceUri);
                Assert.Equal(exp.Name, act.Name);
            }
        }

        private static void AreEqual(AzureAppPushReceiver exp, AzureAppPushReceiver act)
        {
            if (exp != null)
            {
                Assert.Equal(exp.EmailAddress, act.EmailAddress);
                Assert.Equal(exp.Name, act.Name);
            }
        }

        private static void AreEqual(ItsmReceiver exp, ItsmReceiver act)
        {
            if (exp != null)
            {
                Assert.Equal(exp.Name, act.Name);
                Assert.Equal(exp.Region, act.Region);
                Assert.Equal(exp.TicketConfiguration, act.TicketConfiguration);
                Assert.Equal(exp.WorkspaceId, act.WorkspaceId);
                Assert.Equal(exp.ConnectionId, act.ConnectionId);
            }
        }

        private static void AreEqual(AutomationRunbookReceiver exp, AutomationRunbookReceiver act)
        {
            if (exp != null)
            {
                Assert.Equal(exp.AutomationAccountId, act.AutomationAccountId);
                Assert.Equal(exp.IsGlobalRunbook, act.IsGlobalRunbook);
                Assert.Equal(exp.Name, act.Name);
                Assert.Equal(exp.RunbookName, act.RunbookName);
                Assert.Equal(exp.ServiceUri, act.ServiceUri);
            }
        }

        private static void AreEqual(EventHubReceiver exp, EventHubReceiver act)
        {
            if (exp != null)
            {
                Assert.Equal(exp.SubscriptionId, act.SubscriptionId);
                Assert.Equal(exp.EventHubNameSpace, act.EventHubNameSpace);
                Assert.Equal(exp.Name, act.Name);
                Assert.Equal(exp.EventHubName, act.EventHubName);
                Assert.Equal(exp.UseCommonAlertSchema, act.UseCommonAlertSchema);
            }
        }

        private static NotificationRequestBody GetNotificationRequestBody()
        {
            return new NotificationRequestBody
            {
                AlertType = "budget",
                SmsReceivers = new List<SmsReceiver>
                {
                    new SmsReceiver {
                        CountryCode = "84",
                        Name = "Just a name",
                        PhoneNumber = "5555555555"
                    }
                },
                EmailReceivers = new List<EmailReceiver>
                {
                    new EmailReceiver {
                        EmailAddress = "example@test.me",
                        UseCommonAlertSchema = false,
                        Name = "email name"
                    }
                },
                VoiceReceivers = new List<VoiceReceiver>
                {
                    new VoiceReceiver {
                        CountryCode = "1",
                        Name = "Voice name 1",
                        PhoneNumber = "4444444444"
                    }
                }
            };
        }

        private static TestNotificationDetailsResponse GetTestNotificationStatusResponseBody()
        {
            return new TestNotificationDetailsResponse
            {
                Context = new Context
                {
                    ContextType = "Microsoft.Insights/Budget",
                    NotificationSource = "Microsoft.Insights/TestNotification"
                },
                CreatedTime = DateTime.UtcNow.ToString(),
                CompletedTime = DateTime.UtcNow.ToString(),
                State = "Completed",
                ActionDetails = new List<ActionDetail>
                {
                    new ActionDetail {
                        MechanismType = "Email",
                        Name = "Email #1",
                        Status = "Completed",
                        SubState = "Default",
                        SendTime = "2021-10-25T02:06:19.5340048+00:00",
                        Detail = null
                    },
                    new ActionDetail {
                        MechanismType = "Sms",
                        Name = "Sms #1",
                        Status = "Completed",
                        SubState = "Default",
                        SendTime = "2021-10-25T02:06:19.5340048+00:00",
                        Detail = null
                    },
                    new ActionDetail {
                        MechanismType = "Voice",
                        Name = "Sms #1",
                        Status = "Completed",
                        SubState = "Default",
                        SendTime = "2021-10-25T02:06:19.5340048+00:00",
                        Detail = null
                    }
                }
            };
        }

        private static ActionGroupResource GetCreateOrUpdateActionGroupParameter(
            string name = "name1",
            List<EmailReceiver> emailReceivers = null,
            List<SmsReceiver> smsReceivers = null,
            List<WebhookReceiver> webhookReceivers = null,
            List<AzureAppPushReceiver> azureAppPushReceivers = null,
            List<ItsmReceiver> itsmReceivers = null,
            List<AutomationRunbookReceiver> automationRunbookReceivers = null,
            List<EventHubReceiver> eventHubReceivers = null)
        {
            // Name and id won't be serialized since they are readonly
            return new ActionGroupResource(
                id: "long name",
                name: name,
                location: "location",
                groupShortName: name,
                enabled: true,
                tags: new Dictionary<string, string>()
                {
                    {"key1", "val1"}
                },
                emailReceivers: emailReceivers,
                smsReceivers: smsReceivers,
                webhookReceivers: webhookReceivers,
                azureAppPushReceivers: azureAppPushReceivers,
                itsmReceivers: itsmReceivers,
                automationRunbookReceivers: automationRunbookReceivers,
                eventHubReceivers: eventHubReceivers
            );
        }
    }
}