import { Sprite } from './Sprite';
/**
 * Represents a collection of sprites from a source image with some organization in a grid
 */
export class SpriteSheet {
    /**
     * Build a new sprite sheet from a list of sprites
     *
     * Use [[SpriteSheet.fromImageSource]] to create a SpriteSheet from an [[ImageSource]] organized in a grid
     * @param options
     */
    constructor(options) {
        this.sprites = [];
        const { sprites, rows, columns } = options;
        this.sprites = sprites;
        this.rows = rows !== null && rows !== void 0 ? rows : 1;
        this.columns = columns !== null && columns !== void 0 ? columns : this.sprites.length;
    }
    /**
     * Find a sprite by their x/y integer coordinates in the SpriteSheet, for example `getSprite(0, 0)` is the [[Sprite]] in the top-left
     * and `getSprite(1, 0)` is the sprite one to the right.
     * @param x
     * @param y
     */
    getSprite(x, y, options) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j;
        if (x >= this.columns || x < 0) {
            throw Error(`No sprite exists in the SpriteSheet at (${x}, ${y}), x: ${x} should be between 0 and ${this.columns - 1}`);
        }
        if (y >= this.rows || y < 0) {
            throw Error(`No sprite exists in the SpriteSheet at (${x}, ${y}), y: ${y} should be between 0 and ${this.rows - 1}`);
        }
        const spriteIndex = x + y * this.columns;
        const sprite = this.sprites[spriteIndex];
        if (sprite) {
            if (options) {
                const spriteWithOptions = sprite.clone();
                spriteWithOptions.flipHorizontal = (_a = options.flipHorizontal) !== null && _a !== void 0 ? _a : spriteWithOptions.flipHorizontal;
                spriteWithOptions.flipVertical = (_b = options.flipVertical) !== null && _b !== void 0 ? _b : spriteWithOptions.flipVertical;
                spriteWithOptions.width = (_c = options.width) !== null && _c !== void 0 ? _c : spriteWithOptions.width;
                spriteWithOptions.height = (_d = options.height) !== null && _d !== void 0 ? _d : spriteWithOptions.height;
                spriteWithOptions.rotation = (_e = options.rotation) !== null && _e !== void 0 ? _e : spriteWithOptions.rotation;
                spriteWithOptions.scale = (_f = options.scale) !== null && _f !== void 0 ? _f : spriteWithOptions.scale;
                spriteWithOptions.opacity = (_g = options.opacity) !== null && _g !== void 0 ? _g : spriteWithOptions.opacity;
                spriteWithOptions.tint = (_h = options.tint) !== null && _h !== void 0 ? _h : spriteWithOptions.tint;
                spriteWithOptions.origin = (_j = options.origin) !== null && _j !== void 0 ? _j : spriteWithOptions.origin;
                return spriteWithOptions;
            }
            return sprite;
        }
        throw Error(`Invalid sprite coordinates (${x}, ${y}`);
    }
    /**
     * Create a sprite sheet from a sparse set of [[SourceView]] rectangles
     * @param options
     */
    static fromImageSourceWithSourceViews(options) {
        const sprites = options.sourceViews.map((sourceView) => {
            return new Sprite({
                image: options.image,
                sourceView
            });
        });
        return new SpriteSheet({ sprites });
    }
    /**
     * Create a SpriteSheet from an [[ImageSource]] organized in a grid
     *
     * Example:
     * ```
     * const spriteSheet = SpriteSheet.fromImageSource({
     *   image: imageSource,
     *   grid: {
     *     rows: 5,
     *     columns: 2,
     *     spriteWidth: 32, // pixels
     *     spriteHeight: 32 // pixels
     *   },
     *   // Optionally specify spacing
     *   spacing: {
     *     // pixels from the top left to start the sprite parsing
     *     originOffset: {
     *       x: 5,
     *       y: 5
     *     },
     *     // pixels between each sprite while parsing
     *     margin: {
     *       x: 1,
     *       y: 1
     *     }
     *   }
     * })
     * ```
     * @param options
     */
    static fromImageSource(options) {
        var _a;
        const sprites = [];
        options.spacing = (_a = options.spacing) !== null && _a !== void 0 ? _a : {};
        const { image, grid: { rows, columns: cols, spriteWidth, spriteHeight }, spacing: { originOffset, margin } } = options;
        const offsetDefaults = { x: 0, y: 0, ...originOffset };
        const marginDefaults = { x: 0, y: 0, ...margin };
        for (let x = 0; x < cols; x++) {
            for (let y = 0; y < rows; y++) {
                sprites[x + y * cols] = new Sprite({
                    image: image,
                    sourceView: {
                        x: x * spriteWidth + marginDefaults.x * x + offsetDefaults.x,
                        y: y * spriteHeight + marginDefaults.y * y + offsetDefaults.y,
                        width: spriteWidth,
                        height: spriteHeight
                    },
                    destSize: { height: spriteHeight, width: spriteWidth }
                });
            }
        }
        return new SpriteSheet({
            sprites: sprites,
            rows: rows,
            columns: cols
        });
    }
    clone() {
        return new SpriteSheet({
            sprites: this.sprites.map((sprite) => sprite.clone()),
            rows: this.rows,
            columns: this.columns
        });
    }
}
//# sourceMappingURL=SpriteSheet.js.map